Exemplo n.º 1
0
    def make_image(self, options, harpoon_options=None):
        config_root = self.make_temp_dir()
        if harpoon_options is None:
            harpoon_options = {}
        harpoon_options["docker_context"] = self.docker_client
        harpoon_options["no_intervention"] = True
        harpoon_options["docker_context_maker"] = self.new_docker_client

        harpoon = HarpoonSpec().harpoon_spec.normalise(Meta({}, []), harpoon_options)
        if "harpoon" not in options:
            options["harpoon"] = harpoon

        everything = MergedOptions.using({"harpoon": harpoon, "mtime": mtime, "config_root": config_root})
        everything.update({"images": {"awesome_image": options}})

        def make_options():
            base = everything.wrapped()
            base.update(options)
            base["configuration"] = everything
            return base

        meta = Meta(everything, []).at("images").at("awesome_image")
        harpoon_converter = Converter(convert=lambda *args: harpoon, convert_path=["harpoon"])
        image_converter = Converter(
              convert=lambda *args: HarpoonSpec().image_spec.normalise(meta, make_options())
            , convert_path=["images", "awesome_image"]
            )

        everything.add_converter(harpoon_converter)
        everything.add_converter(image_converter)
        everything.converters.activate()

        return everything[["images", "awesome_image"]]
Exemplo n.º 2
0
 def make_image(self, options, harpoon_options=None):
     config_root = self.make_temp_dir()
     if harpoon_options is None:
         harpoon_options = {}
     harpoon_options["docker_context"] = self.docker_client
     harpoon = HarpoonSpec().harpoon_spec.normalise(Meta({}, []), harpoon_options)
     if "harpoon" not in options:
         options["harpoon"] = harpoon
     everything = {"harpoon": harpoon, "mtime": mtime, "_key_name_1": "awesome_image", "config_root": config_root}
     return HarpoonSpec().image_spec.normalise(Meta(everything, []), options)
Exemplo n.º 3
0
        def convert_image(path, val):
            log.info("Converting %s", path)
            everything = path.configuration.root().wrapped()
            meta = Meta(everything, [])
            configuration.converters.started(path)

            base = path.configuration.root().wrapped()
            base.update(configuration.as_dict(ignore=["images"]))
            base.update(val.as_dict(ignore=["images"]))

            base["__image__"] = base
            everything["__image__"] = base

            base["harpoon"] = configuration["harpoon"]
            base["configuration"] = configuration
            return harpoon_spec.image_spec.normalise(meta.at("images").at(image), base)
    def __call__(self, namespace, entry_point_name, collector, known=None):
        if namespace not in self.namespaces:
            log.warning(
                "Unknown plugin namespace\tnamespace=%s\tentry_point=%s\tavailable=%s",
                namespace, entry_point_name, sorted(self.namespaces.keys()))
            return

        entry_point_full_name = "{0}.{1}".format(namespace, entry_point_name)

        entry_points = self.find_entry_points(namespace, entry_point_name,
                                              entry_point_full_name)

        def result_maker(**data):
            return self.namespaces[namespace][0].normalise(
                Meta(data, []), data)

        resolver, extras = self.resolve_entry_points(
            namespace, entry_point_name, collector, result_maker, entry_points,
            entry_point_full_name, known)

        return self.namespaces[namespace][1].normalise(
            Meta({}, []), {
                "namespace": namespace,
                "name": entry_point_name,
                "resolver": resolver,
                "extras": extras
            })
Exemplo n.º 5
0
def pull_arbitrary(collector, image, **kwargs):
    """Pull an arbitrary image"""
    image_index_of = lambda image: urlparse("https://{0}".format(image)).netloc

    if image.startswith("file://"):
        parsed = urlparse(image)
        filename = parsed.netloc + parsed.path
        if not os.path.exists(filename):
            raise HarpoonError("Provided file doesn't exist!", wanted=image)
        with open(filename) as fle:
            image_indexes = [(line.strip(), image_index_of(line.strip()))
                             for line in fle]
    else:
        image_indexes = [(image, image_index_of(image))]

    authentication = collector.configuration.get("authentication",
                                                 NotSpecified)
    for index, (image, image_index) in enumerate(image_indexes):
        image = {
            "image_name": image,
            "harpoon": collector.configuration["harpoon"],
            "commands": ["FROM scratch"],
            "image_index": image_index,
            "assume_role": NotSpecified,
            "authentication": authentication
        }
        meta = Meta(collector.configuration,
                    []).at("images").at("__arbitrary_{0}__".format(index))
        image = HarpoonSpec().image_spec.normalise(meta, image)
        Syncer().pull(image)
Exemplo n.º 6
0
def get_from_env(wanted):
    """Get environment variables from the env"""
    env = sb.listof(env_spec()).normalise(Meta({}, []), wanted)
    missing = [e.env_name for e in env if e.missing]
    if missing:
        raise BespinError("Missing environment variables", missing=missing)
    return dict(e.pair for e in env)
Exemplo n.º 7
0
    def setup_addon_register(self, photons_app, __main__):
        """Setup our addon register"""
        # Create the addon getter and register the crosshair namespace
        self.addon_getter = AddonGetter()
        self.addon_getter.add_namespace("lifx.photons", Result.FieldSpec(),
                                        Addon.FieldSpec())

        # Initiate the addons from our configuration
        register = Register(self.addon_getter, self)

        if "addons" in photons_app:
            addons = photons_app["addons"]
            if type(addons) in (MergedOptions, dict) or getattr(
                    addons, "is_dict", False):
                spec = sb.dictof(sb.string_spec(), sb.listof(sb.string_spec()))
                meta = Meta(photons_app, []).at("addons")
                for namespace, adns in spec.normalise(meta, addons).items():
                    register.add_pairs(*[(namespace, adn) for adn in adns])
        elif photons_app.get("default_activate_all_modules"):
            register.add_pairs(("lifx.photons", "__all__"))

        if __main__ is not None:
            register.add_pairs(("lifx.photons", "__main__"))

        # Import our addons
        register.recursive_import_known()

        # Resolve our addons
        register.recursive_resolve_imported()

        return register
Exemplo n.º 8
0
        def convert_passwords(path, val):
            log.info("Converting %s", path)
            password = str(path)[len("passwords."):]
            configuration.converters.started(path)
            environment = configuration['bespin'].environment

            val_as_dict = configuration["passwords"][password].as_dict()
            if not environment:
                raise BespinError("No environment was provided",
                                  available=list(
                                      configuration["environments"].keys()))

            password_environment_as_dict = {}
            if ["passwords", password, environment] in configuration:
                password_environment_as_dict = configuration[[
                    "passwords", password, environment
                ]].as_dict()

            base = MergedOptions(dont_prefix=path.configuration.dont_prefix,
                                 converters=path.configuration.converters)
            everything = path.configuration.root().wrapped()

            base.update(val_as_dict)
            everything[path] = val_as_dict

            base.update(password_environment_as_dict)
            everything[path].update(password_environment_as_dict)

            for thing in (base, everything):
                thing["__password__"] = val
                thing["__environment__"] = configuration["environments"][
                    environment]

            meta = Meta(everything, [("passwords", ""), (password, "")])
            return bespin_spec.password_spec.normalise(meta, base)
Exemplo n.º 9
0
    def add_configuration(self, configuration, collect_another_source, done,
                          result, src):
        """Used to add a file to the configuration, result here is the yaml.load of the src"""
        def make_mtime_func(source):
            """Lazily calculate the mtime to avoid wasted computation"""
            return lambda context: self.get_committime_or_mtime(
                context, source)

        if "harpoon" in result:
            if "extra_files" in result["harpoon"]:
                spec = sb.listof(
                    sb.formatted(sb.string_spec(),
                                 formatter=MergedOptionStringFormatter))
                meta = Meta(MergedOptions.using(result),
                            []).at("harpoon").at("extra_files")
                for extra in spec.normalise(meta,
                                            result["harpoon"]["extra_files"]):
                    if os.path.abspath(extra) not in done:
                        if not os.path.exists(extra):
                            raise BadConfiguration(
                                "Specified extra file doesn't exist",
                                extra=extra,
                                source=src)
                        collect_another_source(extra)

        if "images" in result and "__images_from__" in result["images"]:
            images_from_path = result["images"]["__images_from__"]

            if isinstance(images_from_path, six.string_types):
                images_from_path = [images_from_path]

            for ifp in images_from_path:

                if not ifp.startswith("/"):
                    ifp = os.path.join(os.path.dirname(src), ifp)

                if not os.path.exists(ifp) or not os.path.isdir(ifp):
                    raise self.BadConfigurationErrorKls(
                        "Specified folder for other configuration files points to a folder that doesn't exist",
                        path="images.__images_from__",
                        value=ifp)

                for root, dirs, files in os.walk(ifp):
                    for fle in files:
                        location = os.path.join(root, fle)
                        if fle.endswith(".yml") or fle.endswith(".yaml"):
                            collect_another_source(
                                location,
                                prefix=[
                                    "images",
                                    os.path.splitext(os.path.basename(fle))[0]
                                ],
                                extra={"mtime": make_mtime_func(location)})

            del result["images"]["__images_from__"]

        if "mtime" not in result:
            result["mtime"] = make_mtime_func(src)
        configuration.update(result, source=src)
 def __init__(self, extras=sb.NotSpecified, post_register=False):
     self.post_register = post_register
     if post_register and extras not in (None, {}, sb.NotSpecified):
         msg = "Sorry, can't specify ``extras`` and ``post_register`` at the same time"
         raise ProgrammerError(msg)
     spec = sb.listof(
         sb.tuple_spec(sb.string_spec(), sb.listof(sb.string_spec())))
     self.extras = spec.normalise(Meta({}, []), extras)
Exemplo n.º 11
0
 def converter(p, v):
     log.info("Converting %s", p)
     meta = Meta(p.configuration, [(thing, "")])
     configuration.converters.started(p)
     if thing in by_name:
         return by_name[thing].normalise(meta, v)
     else:
         return getattr(aws_syncr_spec, "{0}_spec".format(thing)).normalise(meta, v)
Exemplo n.º 12
0
        def convert_image(path, val):
            log.info("Converting %s", path)
            everything = path.configuration.root().wrapped()
            meta = Meta(everything, [])
            configuration.converters.started(path)

            base = path.configuration.root().wrapped()
            base.update(configuration.as_dict(ignore=["images"]))
            base.update(val.as_dict(ignore=["images"]))

            base["__image__"] = base
            everything["__image__"] = base

            base["harpoon"] = configuration["harpoon"]
            base["configuration"] = configuration
            return harpoon_spec.image_spec.normalise(
                meta.at("images").at(image), base)
Exemplo n.º 13
0
 def convert_tasks(path, val):
     spec = bespin_spec.tasks_spec(available_actions)
     meta = Meta(path.configuration.root(),
                 [('stacks', ""), (stack, ""), ('tasks', "")])
     configuration.converters.started(path)
     tasks = spec.normalise(meta, val)
     for task in tasks.values():
         task.stack = stack
     return tasks
Exemplo n.º 14
0
 def convert_tasks(path, val):
     spec = harpoon_spec.tasks_spec(available_actions)
     meta = Meta(path.configuration.root(),
                 [('images', ""), (image, ""), ('tasks', "")])
     configuration.converters.started(path)
     tasks = spec.normalise(meta, val)
     for task in tasks.values():
         task.image = image
     return tasks
Exemplo n.º 15
0
    def from_options(kls, options):
        """Create a Filter based on the provided dictionary"""
        if isinstance(options, dict):
            for option in options:
                if option not in kls.fields:
                    log.warning(
                        hp.lc("Unknown option provided for filter",
                              wanted=option))

        return kls.FieldSpec().normalise(Meta.empty(), options)
Exemplo n.º 16
0
    def get_string(self, key):
        """Get a string from all_options"""
        if key not in self.all_options:
            kwargs = {}
            if len(self.chain) > 1:
                kwargs['source'] = Meta(self.all_options, self.chain[-2]).source
            raise BadOptionFormat("Can't find key in options", key=key, chain=self.chain, **kwargs)

        val = self.all_options[key]
        return val
Exemplo n.º 17
0
 def pack_payload(kls, message_type, data, messages_register=None):
     """
     Given some payload data as a dictionary and it's ``pkt_type``, return a
     hexlified string of the payload.
     """
     for k in (messages_register or [kls]):
         if int(message_type) in k.by_type:
             return k.by_type[int(message_type)].Payload.normalise(
                 Meta.empty(), data).pack()
     raise BadConversion("Unknown message type!", pkt_type=message_type)
Exemplo n.º 18
0
        def convert_stack(path, val):
            log.info("Converting %s", path)
            configuration.converters.started(path)
            environment = configuration['bespin'].environment

            config_as_dict = configuration.as_dict(ignore=["stacks"])
            val_as_dict = val.as_dict(ignore=["stacks"])
            if not environment or environment is NotSpecified:
                raise BespinError("No environment was provided",
                                  available=list(
                                      configuration["environments"].keys()))

            env = configuration[["environments", environment]]
            if isinstance(env, six.string_types):
                environment_as_dict = configuration[["environments",
                                                     env]].as_dict()
                env = configuration[["environments", env]]
            else:
                environment_as_dict = configuration[[
                    "environments", environment
                ]].as_dict()

            stack_environment = {}
            stack_environment_as_dict = {}
            if ["stacks", stack, environment] in configuration:
                stack_environment = configuration[[
                    "stacks", stack, environment
                ]]
                stack_environment_as_dict = stack_environment.as_dict()

            # `base` is used for the majority of the values
            base = path.configuration.root().wrapped()
            base.update(config_as_dict)
            base.update(val_as_dict)
            base.update(environment_as_dict)
            base.update(stack_environment_as_dict)

            # `everything` is used for formatting options
            # Ideally it matches base
            # The difference here is that we want to maintain source information
            everything = path.configuration.root().wrapped()
            everything[path] = MergedOptions.using(configuration, val, env,
                                                   stack_environment)

            for thing in (base, everything):
                thing["bespin"] = configuration["bespin"]
                thing["environment"] = environment
                thing["configuration"] = configuration
                thing["__stack__"] = val
                thing["__environment__"] = configuration["environments"][
                    environment]
                thing["__stack_name__"] = stack

            meta = Meta(everything, [("stacks", ""), (stack, "")])
            return bespin_spec.stack_spec.normalise(meta, base)
Exemplo n.º 19
0
async def set_chain_state(collector, target, reference, artifact, **kwargs):
    """
    Set the state of colors on your tile

    ``lan:set_chain_state d073d5f09124 -- '{"colors": [[[0, 0, 0, 3500], [0, 0, 0, 3500], ...], [[0, 0, 1, 3500], ...], ...], "tile_index": 1, "length": 1, "x": 0, "y": 0, "width": 8}'``

    Where the colors is a grid of 8 rows of 8 ``[h, s, b, k]`` values.
    """
    options = collector.configuration["photons_app"].extra_as_json

    if "colors" in options:
        spec = sb.listof(
            sb.listof(
                list_spec(sb.integer_spec(), sb.float_spec(), sb.float_spec(),
                          sb.integer_spec())))
        colors = spec.normalise(Meta.empty().at("colors"), options["colors"])

        row_lengths = [len(row) for row in colors]
        if len(set(row_lengths)) != 1:
            raise PhotonsAppError(
                "Please specify colors as a grid with the same length rows",
                got=row_lengths)

        num_cells = sum(len(row) for row in colors)
        if num_cells != 64:
            raise PhotonsAppError("Please specify 64 colors", got=num_cells)

        cells = []
        for row in colors:
            for col in row:
                cells.append({
                    "hue": col[0],
                    "saturation": col[1],
                    "brightness": col[2],
                    "kelvin": col[3]
                })

        options["colors"] = cells
    else:
        raise PhotonsAppError(
            "Please specify colors in options after -- as a grid of [h, s, b, k]"
        )

    missing = []
    for field in TileMessages.SetState64.Payload.Meta.all_names:
        if field not in options and field not in ("duration", "reserved6"):
            missing.append(field)

    if missing:
        raise PhotonsAppError("Missing options for the SetTileState message",
                              missing=missing)

    options["res_required"] = False
    msg = TileMessages.SetState64.empty_normalise(**options)
    await target.script(msg).run_with_all(reference)
Exemplo n.º 20
0
    def make_image(self, options, harpoon_options=None):
        config_root = self.make_temp_dir()
        if harpoon_options is None:
            harpoon_options = {}
        harpoon_options["docker_context"] = self.docker_client
        harpoon_options["docker_context_maker"] = self.new_docker_client

        harpoon = HarpoonSpec().harpoon_spec.normalise(Meta({}, []), harpoon_options)
        if "harpoon" not in options:
            options["harpoon"] = harpoon

        everything = MergedOptions.using({"harpoon": harpoon, "mtime": mtime, "_key_name_1": "awesome_image", "config_root": config_root})

        harpoon_converter = Converter(convert=lambda *args: harpoon, convert_path=["harpoon"])
        everything.add_converter(harpoon_converter)
        everything.converters.activate()

        if "configuration" not in options:
            options["configuration"] = everything
        return HarpoonSpec().image_spec.normalise(Meta(everything, []), options)
Exemplo n.º 21
0
 def get_string(self, key):
     """Get a string from all_options"""
     if key not in self.all_options:
         kwargs = {}
         if len(self.chain) > 1:
             kwargs['source'] = Meta(self.all_options,
                                     self.chain[-2]).source
         raise BadOptionFormat("Can't find key in options",
                               key=key,
                               chain=self.chain,
                               **kwargs)
     return super(MergedOptionStringFormatter, self).get_string(key)
Exemplo n.º 22
0
    def pack(kls, data, protocol_register, unknown_ok=False):
        """
        Return a hexlified string of the data.

        This uses ``pkt_type`` and ``protocol`` in the data, along with the
        protocol_register to find the appropriate class to use to perform the
        packing.
        """
        if "pkt_type" in data:
            message_type = data["pkt_type"]
        elif "pkt_type" in data.get("protocol_header", {}):
            message_type = data["protocol_header"]["pkt_type"]
        else:
            raise BadConversion(
                "Don't know how to pack this dictionary, it doesn't specify a pkt_type!"
            )

        if "protocol" in data:
            protocol = data["protocol"]
        elif "frame_header" in data and "protocol" in data["frame_header"]:
            protocol = data["frame_header"]["protocol"]
        else:
            raise BadConversion(
                "Don't know how to pack this dictionary, it doesn't specify a protocol!"
            )

        prot = protocol_register.get(protocol)
        if prot is None:
            raise BadConversion("Unknown packet protocol",
                                wanted=protocol,
                                available=list(protocol_register))
        Packet, messages_register = prot

        for k in (messages_register or [kls]):
            if message_type in k.by_type:
                return k.by_type[message_type].normalise(Meta.empty(),
                                                         data).pack()
        if unknown_ok:
            return Packet.normalise(Meta.empty(), data).pack()
        raise BadConversion("Unknown message type!", pkt_type=message_type)
Exemplo n.º 23
0
    def get_string(self, key):
        """Get a string from all_options"""
        if key not in self.all_options:
            kwargs = {}
            if len(self.chain) > 1:
                kwargs['source'] = Meta(self.all_options, self.chain[-2]).source
            raise BadOptionFormat("Can't find key in options", key=key, chain=self.chain, **kwargs)

        # Make sure we special case the "content" option
        if type(key) is str and key.startswith("content."):
            return self.no_format(self.all_options["content"][key[8:]])
        if type(key) is list and len(key) is 2 and key[0] == "content":
            return self.no_format(self.all_options[key])

        return super(MergedOptionStringFormatter, self).get_string(key)
Exemplo n.º 24
0
async def set_attr(collector,
                   target,
                   reference,
                   artifact,
                   broadcast=False,
                   **kwargs):
    """
    Set attributes on your globes

    ``target:set_attr d073d5000000 color -- '{"hue": 360, "saturation": 1, "brightness": 1}'``

    This does the same thing as ``get_attr`` but will look for ``Set<Attr>``
    message and initiates it with the options found after the ``--``.

    So in this case it will create ``SetColor(hue=360, saturation=1, brightness=1)``
    and send that to the device.
    """
    protocol_register = collector.configuration["protocol_register"]

    if artifact in (None, "", NotSpecified):
        raise BadOption(
            "Please specify what you want to get\nUsage: {0} <target>:set_attr <reference> <attr_to_get> -- '{{<options>}}'"
            .format(sys.argv[0]))

    kls_name = "Set{0}".format("".join(part.capitalize()
                                       for part in artifact.split("_")))

    setter = None
    for messages in protocol_register.message_register(1024):
        for kls in messages.by_type.values():
            if kls.__name__ == kls_name:
                setter = kls
                break

    if setter is None:
        raise BadOption(
            "Sorry, couldn't find the message type {0}".format(kls_name))

    photons_app = collector.configuration["photons_app"]

    extra = photons_app.extra_as_json

    if "extra_payload_kwargs" in kwargs:
        extra.update(kwargs["extra_payload_kwargs"])

    script = target.script(setter.normalise(Meta.empty(), extra))
    async for pkt, _, _ in script.run_with(reference, broadcast=broadcast):
        print("{0}: {1}".format(pkt.serial, repr(pkt.payload)))
Exemplo n.º 25
0
async def get_attr(collector, target, reference, artifact, **kwargs):
    """
    Get attributes from your globes

    ``target:get_attr d073d5000000 color``

    Where ``d073d5000000`` is replaced with the serial of the device you are
    addressing and ``color`` is replaced with the attribute you want.

    This task works by looking at all the loaded LIFX binary protocol messages
    defined for the 1024 protocol and looks for ``Get<Attr>``.

    So if you want the ``color`` attribute, it will look for the ``GetColor``
    message and send that to the device and print out the reply packet we get
    back.
    """
    protocol_register = collector.configuration["protocol_register"]

    if artifact in (None, "", NotSpecified):
        raise BadOption(
            "Please specify what you want to get\nUsage: {0} <target>:get_attr <reference> <attr_to_get>"
            .format(sys.argv[0]))

    kls_name = "Get{0}".format("".join(part.capitalize()
                                       for part in artifact.split("_")))

    getter = None
    for messages in protocol_register.message_register(1024):
        for kls in messages.by_type.values():
            if kls.__name__ == kls_name:
                getter = kls
                break

    if getter is None:
        raise BadOption(
            "Sorry, couldn't find the message type {0}".format(kls_name))

    photons_app = collector.configuration["photons_app"]

    extra = photons_app.extra_as_json

    if "extra_payload_kwargs" in kwargs:
        extra.update(kwargs["extra_payload_kwargs"])

    script = target.script(getter.normalise(Meta.empty(), extra))
    async for pkt, _, _ in script.run_with(reference, **kwargs):
        print("{0}: {1}".format(pkt.serial, repr(pkt.payload)))
Exemplo n.º 26
0
def encrypt_password(collector, stack, artifact, **kwargs):
    """Convert plain text password into crypto text"""
    if artifact is None:
        key = stack
    else:
        key = artifact

    configuration = collector.configuration
    key = valid_password_key().normalise(Meta(configuration, []), key)
    password_options = configuration["passwords"][key]

    log.info("Generating a crypto_text for the %s password using %s as the KMS key id", key, password_options.KMSMasterKey)
    plain_text = getpass("Specify the password: "******"bespin"].credentials.kms.encrypt(password_options.KMSMasterKey, plain_text, password_options.encryption_context, password_options.grant_tokens)
    log.info("Generated crypto text for %s", key)
    print(base64.b64encode(res["CiphertextBlob"]).decode('utf-8'))
Exemplo n.º 27
0
    def extra_prepare(self, configuration, args_dict):
        """Called before the configuration.converters are activated"""
        harpoon = MergedOptions.using(
            configuration.get('harpoon', MergedOptions()).as_dict(),
            dict(args_dict.get("harpoon", MergedOptions()).items())).as_dict()

        # Args_dict may itself be a MergedOptions
        while "harpoon" in args_dict:
            del args_dict["harpoon"]

        # Create the addon getter and register the crosshair namespace
        self.addon_getter = AddonGetter()
        self.addon_getter.add_namespace("harpoon.crosshairs",
                                        Result.FieldSpec(), Addon.FieldSpec())

        # Initiate the addons from our configuration
        self.register = Register(self.addon_getter, self)
        if ("addons" in harpoon) and (
                type(harpoon["addons"]) in (MergedOptions, dict)
                or getattr(harpoon["addons"], "is_dict", False)):
            for namespace, adns in sb.dictof(
                    sb.string_spec(), sb.listof(sb.string_spec())).normalise(
                        Meta(harpoon, []).at("addons"),
                        harpoon["addons"]).items():
                self.register.add_pairs(*[(namespace, adn) for adn in adns])

        # Import our addons
        self.register.recursive_import_known()

        # Resolve our addons
        self.register.recursive_resolve_imported()

        # Make sure images is started
        if "images" not in self.configuration:
            self.configuration["images"] = {}

        # Add our special stuff to the configuration
        self.configuration.update(
            {
                "$@": harpoon.get("extra", ""),
                "bash": args_dict["bash"] or NotSpecified,
                "harpoon": harpoon,
                "command": args_dict['command'] or NotSpecified,
                "assume_role": args_dict["assume_role"] or NotSpecified
            },
            source="<args_dict>")
Exemplo n.º 28
0
    def add_configuration(self, configuration, collect_another_source, done,
                          result, src):
        """
        Used to add a file to the configuration, result here is the yaml.load
        of the src.

        If the configuration we're reading in has ``photons_app.extra_files``
        then this is treated as a list of strings of other files to collect.
        """
        # Make sure to maintain the original config_root
        if "config_root" in configuration:
            # if we already have a config root then we only keep new config root if it's not the home location
            # i.e. if it is the home configuration, we don't delete the new config_root
            if configuration["config_root"] != os.path.dirname(
                    self.home_dir_configuration_location()):
                if "config_root" in result:
                    del result["config_root"]

        config_root = configuration.get("config_root")
        if config_root and src.startswith(config_root):
            src = "{{config_root}}/{0}".format(src[len(config_root) + 1:])

        configuration.update(result, source=src)

        if "photons_app" in result:
            if "extra_files" in result["photons_app"]:
                spec = sb.listof(
                    sb.formatted(sb.string_spec(),
                                 formatter=MergedOptionStringFormatter))
                config_root = {
                    "config_root":
                    result.get("config_root", configuration.get("config_root"))
                }
                meta = Meta(MergedOptions.using(result, config_root),
                            []).at("photons_app").at("extra_files")
                for extra in spec.normalise(
                        meta, result["photons_app"]["extra_files"]):
                    if os.path.abspath(extra) not in done:
                        if not os.path.exists(extra):
                            raise BadConfiguration(
                                "Specified extra file doesn't exist",
                                extra=extra,
                                source=src)
                        collect_another_source(extra)
Exemplo n.º 29
0
def downtime(collector, stack, method="downtime", **kwargs):
    """Downtime this stack in alerting systems"""
    if stack.downtimer_options is NotSpecified:
        raise BespinError("Nothing to downtime!")

    env = sb.listof(env_spec()).normalise(Meta({}, []), ["USER", "DURATION", "COMMENT"])
    missing = [e.env_name for e in env if e.missing]
    if missing:
        raise BespinError("Missing environment variables", missing=missing)
    provided_env = dict(e.pair for e in env)

    author = provided_env["USER"]
    comment = provided_env["COMMENT"]
    duration = provided_env["DURATION"]

    downtimer = Downtimer(stack.downtimer_options, dry_run=collector.configuration["bespin"].dry_run)
    for system, options in stack.alerting_systems.items():
        downtimer.register_system(system, options)

    getattr(downtimer, method)(duration, author, comment)
Exemplo n.º 30
0
async def apply_theme(collector, target, reference, artifact, **kwargs):
    """
    Apply a theme to specified device

    ``lan:apply_theme d073d5000001 -- `{"colors": <colors>, "theme": "SPLOTCH"}'``

    If you don't specify serials, then the theme will apply to all devices found on the network.

    colors must be an array of ``{"hue": <hue>, "saturation": <saturation>, "brightness": <brightness>, "kelvin": <kelvin>}``

    theme must be a valid theme type and defaults to SPLOTCH

    You may also specify ``duration`` which is how long to take to apply in seconds.

    And you may also supply ``hue``, ``saturation``, ``brightness`` and ``kelvin`` to override the specified colors.
    """
    options = Options.FieldSpec().normalise(
        Meta.empty(), collector.configuration["photons_app"].extra_as_json)

    async with target.session() as afr:
        await do_apply_theme(target, reference, afr, options)
Exemplo n.º 31
0
    def add_configuration(self, configuration, collect_another_source, done,
                          result, src):
        """Used to add a file to the configuration, result here is the yaml.load of the src"""
        if "bespin" in result:
            if "extra_files" in result.get("bespin", {}):
                spec = sb.listof(
                    sb.formatted(sb.string_spec(),
                                 formatter=MergedOptionStringFormatter))
                for extra in spec.normalise(
                        Meta(configuration, []).at("bespin").at("extra_files"),
                        result["bespin"]["extra_files"]):
                    extra = os.path.join(result['config_root'], extra)
                    if os.path.abspath(extra) not in done:
                        if not os.path.exists(extra):
                            raise BadConfiguration(
                                "Specified extra file doesn't exist",
                                extra=extra,
                                source=src)
                        collect_another_source(extra)

        configuration.update(result, dont_prefix=[dictobj], source=src)
Exemplo n.º 32
0
            assert not hasattr(changed, "three")
            assert not hasattr(changed, "four")
            self.assertEqual(changed.one, sb.NotSpecified)
            self.assertEqual(changed.two, sb.NotSpecified)

        it "allows setting all values to be required":
            class Original(dictobj.Spec):
                one = dictobj.Field(sb.string_spec)
                two = dictobj.Field(sb.integer_spec)
                three = dictobj.Field(sb.string_spec)
                four = dictobj.Field(sb.any_spec)

            Changed = Original.selection("Changed", ["one", "two"], all_required=True)

            m = Meta.empty()
            error1 = BadSpecValue("Expected a value but got none", meta=m.at("two"))
            error2 = BadSpecValue("Expected a value but got none", meta=m.at("one"))

            with self.fuzzyAssertRaisesError(BadSpecValue, _errors=[error1, error2]):
                changed = Changed.FieldSpec().normalise(m, {})

        it "can override all_required with optional":
            class Original(dictobj.Spec):
                one = dictobj.Field(sb.string_spec)
                two = dictobj.Field(sb.integer_spec)
                three = dictobj.Field(sb.string_spec)
                four = dictobj.Field(sb.any_spec)

            Changed = Original.selection("Changed", ["one", "two"], all_required=True, optional=["two"])
Exemplo n.º 33
0
 def empty_normalise(self, **kwargs):
     """Normalise val with the spec from self.make_spec"""
     return self.normalise(Meta.empty(), kwargs)
Exemplo n.º 34
0
        blah_image = self.unique_val()
        md5 = hashlib.md5(json.dumps({"content": content}).encode('utf-8')).hexdigest()
        md52 = hashlib.md5(json.dumps({"content": {"image": "blah2", "path": "/tmp/stuff"}}, sort_keys=True).encode("utf-8")).hexdigest()

        blah2_image = mock.Mock(name="blah2", image_name="blah2", from_name="somewhere-blah2")
        blah3_image = mock.Mock(name="blah3", image_name="blah3", from_name="somewhere-blah3")

        everything = MergedOptions.using(
              { "one": 1, "two": 2, "three": 3, "harpoon": self.harpoon, "config_root": "."
              , "images":
                { "blah2": blah2_image
                , "blah3": blah3_image
                }
              }
            )
        meta = Meta(everything, [])

        commands = [
              "FROM somewhere as base"
            , ["FROM", blah_image]
            , "ADD something /somewhere"
            , "COPY --from=blah something /somewhere"
            , ["ENV ONE", "{one}"]
            , ["ENV", ["TWO {two}", "THREE {three}"]]
            , ["ADD", {"get": ["blah", "and", "stuff"], "prefix": "/projects"}]
            , {"ADD": {"content": content, "dest": "the_destination"}}
            , {"ADD": {"content": content, "dest": "the_destination2"}}
            , {"ADD": {"content": {"image": "{images.blah2}", "path": "/tmp/stuff"}, "dest": "the_destination3"}}
            , {"COPY": {"from": "{images.blah2}", "path": "/tmp/stuff", "to": "copy_destination"}}
            , {"COPY": {"from": 1, "path": "/tmp/stuff", "to": "copy_destination"}}
            , ["FROM", "{images.blah3}", "as wat"]