示例#1
0
class Link(Resource):
    """ A resource representing a symbolic link. The link will be from `name`
    to `to`. If you specify owner, group and/or mode then these settings will
    be applied to the link itself, not to the object linked to.

    For example::

      Link:
        name: /etc/init.d/exampled
        to: /usr/local/example/sbin/exampled
        owner: root
        group: root

    """

    name = Property(FullPath)
    """The name of the file this resource represents."""

    owner = Property(String, default="root")
    """A unix username or UID who will own created objects. An owner that
    begins with a digit will be interpreted as a UID, otherwise it will be
    looked up using the python 'pwd' module."""

    group = Property(String, default="root")
    """A unix group or GID who will own created objects. A group that begins
    with a digit will be interpreted as a GID, otherwise it will be looked up
    using the python 'grp' module."""

    to = Property(FullPath)
    """ The pathname to which to link the symlink. Dangling symlinks ARE
示例#2
0
class Directory(Resource):
    """ A directory on disk. Directories have limited metadata, so this
    resource is quite limited.

    For example::

        Directory:
          name: /var/local/data
          owner: root
          group: root
          mode: 0755

    """

    name = Property(FullPath)
    """ The full path to the directory on disk """

    owner = Property(String, default="root")
    """ The unix username who should own this directory, by default this is 'root' """

    group = Property(String, default="root")
    """ The unix group who should own this directory, by default this is 'root' """

    mode = Property(Octal, default="755")
    """ The octal mode that represents this directory's permissions, by default this is '755'. """

    parents = Property(Boolean, default=False)
    """ Create parent directories as needed, using the same ownership and
示例#3
0
class Mount(Resource):

    name = Property(FullPath)
    """The name of the file this resource represents."""

    """ The type of mount e.g. ext3 """
    fs_type = Property(String)

    """ The options to pass to mount """
    options = Property(String, default="defaults")

    device = Property(FullPath)
    """ The pathname to which to link the symlink. Dangling symlinks ARE
示例#4
0
class Special(Resource):
    """ A special file, as created by mknod. """

    name = Property(FullPath)
    """ The full path to the special file on disk. """

    owner = Property(String, default="root")
    """ The unix user who should own this special file. """

    group = Property(String, default="root")
    """ The unix group who should own this special file. """

    mode = Property(Octal, default=0o644)
    """ The octal representation of the permissions for this special file. """

    type = Property(String, default="fifo")
    """ One of the following strings:

      block
        create a block (buffered) special file
      character
        create a character (unbuffered) special file
      fifo
        create a fifo

    It defaults to fifo
    """

    major = Property(Integer)
    """ The major number for the special file. If the type of the special file
    is block or character, then this must be specified. """

    minor = Property(Integer)
    """ The minor number for the special file. If the type of the special file
示例#5
0
class Package(Resource):
    """ Represents an operating system package, installed and managed via the
    OS package management system. For example, to ensure these three packages
    are installed::

        Package:
            - name: apache2
            - name: zip
            - name: xsltproc

    """

    name = Property(String)
    """ The name of the package. This can be a single package or a list can be
    supplied. """

    version = Property(String)
    """ The version of the package, if only a single package is specified and
    the appropriate provider supports it (the Apt provider does not support
    it). """

    purge = Property(Boolean, default=False)
    """ When removing a package, whether to purge it or not. """
示例#6
0
文件: group.py 项目: mitchellrj/yaybu
class Group(Resource):
    """ A resource representing a unix group stored in the /etc/group file.
    groupadd and groupmod are used to actually make modifications.

    For example::

        Group:
            name: zope
            system: true
    """

    name = Property(String)
    """ The name of the unix group. """

    gid = Property(Integer)
    """ The group ID associated with the group. If this is not specified one will be chosen. """

    system = Property(Boolean, default=False)
    """ Whether or not this is a system group - i.e. the new group id will be
    taken from the system group id list. """

    password = Property(String)
    """ The password for the group, if required """
示例#7
0
class Service(Resource):
    """ This represents service startup and shutdown via an init daemon. """

    name = Property(String)
    """ A unique name representing an initd service.

    This would normally match the name as it appears in /etc/init.d.
    """

    priority = Property(Integer, default=99)
    """ Priority of the service within the boot order.

    This attribute will have no effect when using a dependency or event based
    init.d subsystem like upstart or systemd. """

    start = Property(String)
    """ A command that when executed will start the service.

    If not provided, the provider will use the default service start invocation
    for the init.d system in use.
    """

    stop = Property(String)
    """ A command that when executed will start the service.

    If not provided, the provider will use the default service stop invocation
    for the init.d system in use.
    """

    restart = Property(String)
    """ A command that when executed will restart the service.

    If not provided, the provider will use the default service restart invocation
    for the init.d system in use. If it is not possible to automatically determine
    if the restart script is avilable the service will be stopped and started instead.
    """

    reconfig = Property(String)
    """ A command that when executed will make the service reload its
    configuration file. """

    running = Property(String)
    """ A comamnd to execute to determine if a service is running. Should have an exit code of 0 for success. """

    pidfile = Property(FullPath)
    """ Where the service creates its pid file.
示例#8
0
文件: patch.py 项目: mitchellrj/yaybu
class Patch(Resource):
    """
    A provider for this resource will copy a source file from the target system
    and apply a patch to it.

    For example::

        - Patch:
            target: /output
            source: /output
            patch: localfile

    """

    name = Property(FullPath)
    """The full path to the file this resource represents."""

    source = Property(FullPath)
    """ The full path to a file to copy to target and patch """

    patch = Property(File)

    strip = Property(Integer, default=0)
    """ Strip the smallest prefix containing ``strip`` leading slashes from
    each file name found in the patch. """

    owner = Property(String, default="root")
    """A unix username or UID who will own created objects. An owner that
    begins with a digit will be interpreted as a UID, otherwise it will be
    looked up using the python 'pwd' module."""

    group = Property(String, default="root")
    """A unix group or GID who will own created objects. A group that begins
    with a digit will be interpreted as a GID, otherwise it will be looked up
    using the python 'grp' module."""

    mode = Property(Octal, default="644")
    """A mode representation as an octal. This can begin with leading zeros if
    you like, but this is not required. DO NOT use yaml Octal representation
    (0o666), this will NOT work."""

    template_args = Property(Dict, default={})
    """The arguments passed to the template."""
示例#9
0
class Execute(Resource):

    """ Execute a command. This command is not executed in a shell - if you
    want a shell, run it (for example bash -c).

    For example::

        Execute:
          name: core_packages_apt_key
          command: apt-key adv --keyserver keyserver.ubuntu.com --recv-keys {{source.key}}

    A much more complex example. This shows executing a command if a checkout synchronises::

        Execute.foreach bi in {{flavour.base_images}}:
          name: base-image-{{bi}}
          policy:
              apply:
                  when: sync
                  on: /var/local/checkouts/ci
          command: ./vmbuilder-{{bi}}
          cwd: /var/local/checkouts/ci
          user: root

    """

    name = Property(String)
    """ The name of this resource. This should be unique and descriptive, and
    is used so that resources can reference each other. """

    command = Property(String)
    """ If you wish to run a single command, then this is the command. """

    commands = Property(List)
    """ If you wish to run multiple commands, provide a list """

    cwd = Property(FullPath, default='/')
    """ The current working directory in which to execute the command. """

    environment = Property(Dict)
    """

    The environment to provide to the command, for example::

        Execute:
            name: example
            command: echo $FOO
            environment:
                FOO: bar
    """

    returncode = Property(Integer, default=0)
    """ The expected return code from the command, defaulting to 0. If the
    command does not return this return code then the resource is considered
    to be in error. """

    user = Property(String, default="root")
    """ The user to execute the command as.
    """

    group = Property(String)
    """ The group to execute the command as.
    """

    umask = Property(Octal, default='022')
    """ The umask to use when executing this command """

    unless = Property(String, default="")
    """ A command to run to determine is this execute should be actioned
    """

    creates = Property(FullPath)
    """ The full path to a file that execution of this command creates. This
    is used like a "touch test" in a Makefile. If this file exists then the
    execute command will NOT be executed. """

    touch = Property(FullPath)
    """ The full path to a file that yaybu will touch once this command has
示例#10
0
文件: user.py 项目: mitchellrj/yaybu
class User(Resource):
    """ A resource representing a UNIX user in the password database. The underlying implementation currently uses the "useradd" and "usermod" commands to implement this resource.

    This resource can be used to create, change or delete UNIX users.

    For example::

        User:
          name: django
          fullname: Django Software Owner
          home: /var/local/django
          system: true
          disabled-password: true

    """

    name = Property(String)
    """ The username this resource represents. """

    password = Property(String)
    """ The encrypted password, as returned by crypt(3). You should make sure
    this password respects the system's password policy. """

    fullname = Property(String)
    """ The comment field for the password file - generally used for the user's full name. """

    home = Property(FullPath)
    """ The full path to the user's home directory. """

    uid = Property(Integer)
    """ The user identifier for the user. This must be a non-negative integer. """

    gid = Property(Integer)
    """ The group identifier for the user. This must be a non-negative integer. """

    group = Property(String)
    """ The primary group for the user, if you wish to specify it by name. """

    groups = Property(List)
    """ A list of supplementary groups that the user should be a member of. """

    append = Property(Boolean, default=True)
    """ A boolean that sets how to apply the groups a user is in. If true then yaybu will
    add the user to groups as needed but will not remove a user from a group. If false then yaybu will replace
    all groups the user is a member of. Thus if a process outside of yaybu adds you to a group,
    the next deployment would remove you again. """

    system = Property(Boolean, default=True)
    # has no effect on modification, only creation
    """ A boolean representing whether this user is a system user or not. This only takes effect on
    creation - a user cannot be changed into a system user once created
    without deleting and recreating the user. """

    shell = Property(FullPath, default="/bin/bash")
    """ The full path to the shell to use. """

    disabled_password = Property(Boolean, default=False)
    """ A boolean for whether the password is locked for this account. """

    disabled_login = Property(Boolean, default=False)
    """ A boolean for whether this entire account is locked or not. """
示例#11
0
class Checkout(Resource):
    """ This represents a "working copy" from a Source Code Management system.
    This could be provided by, for example, Subversion or Git remote
    repositories.

    Note that this is '*a* checkout', not 'to checkout'. This represents the
    resource itself on disk. If you change the details of the working copy
    (for example changing the branch) the provider will execute appropriate
    commands (such as `svn switch`) to take the resource to the desired state.
    """

    name = Property(FullPath)
    """ The full path to the working copy on disk. """

    repository = Property(String)
    """ The identifier for the repository - this could be an http url for
    subversion or a git url for git, for example. """

    branch = Property(String)
    """ The name of a branch to check out, if required. """

    tag = Property(String)
    """ The name of a tag to check out, if required. """

    revision = Property(String)
    """ The revision to check out or move to. """

    scm = Property(String)
    """ The source control management system to use, e.g. subversion, git. """

    scm_username = Property(String)
    """ The username for the remote repository """

    scm_password = Property(String)
    """ The password for the remote repository. """

    user = Property(String, default="root")
    """ The user to perform actions as, and who will own the resulting files. """

    group = Property(String, default="root")
    """ The group to perform actions as. """

    mode = Property(Octal, default="755")
    """A mode representation as an octal. This can begin with leading zeros if
示例#12
0
class Resource(object):
    """ A resource represents a resource that can be configured on the system.
    This might be as simple as a symlink or as complex as a database schema
    migration. Resources have policies that represent how the resource is to
    be treated. Providers are the implementation of the resource policy.

    Resource definitions specify the complete set of attributes that can be
    configured for a resource. Policies define which attributes must be
    configured for the policy to be used.

    """

    __metaclass__ = ResourceType

    policies = AvailableResourcePolicies()
    """ A dictionary of policy names mapped to policy classes (not objects).

    These are the policies for this resource class.

    Here be metaprogramming magic.

    Dynamically allocated as Yaybu starts up this is effectively static once
    we're up and running. The combination of this attribute and the policy
    argument below is sufficient to determine which provider might be
    appropriate for this resource.

    """

    policy = Property(PolicyArgument)
    """ The list of policies provided by configuration. This is an argument
    like any other, but has a complex representation that holds the conditions
    and options for the policies as specified in the input file. """

    name = Property(String)

    watch = Property(List, default=[])
    """ A list of files to monitor while this resource is applied

    The file will be hashed before and after a resource is applied.
    If the hash changes, then it will be like a policy has been applied
    on that file.

    For example::

        resources.append:
          - Execute:
              name: buildout-foobar
              command: buildout2.6
              watch:
                - /var/local/sites/foobar/apache/apache.cfg

          - Service:
              name: apache2
              policy:
                restart:
                  when: watched
                  on: File[/var/local/sites/foobar/apache/apache.cfg]
    """
    def __init__(self, inner):
        """ Takes a reference to a Yay AST node """
        self.inner = PythonicWrapper(inner)
        self.inner.parent = inner.parent
        self.observers = collections.defaultdict(list)

        for k in dir(self):
            prop = getattr(self, k)
            if isinstance(prop, Property):
                i = getattr(self.inner, k)
                i.inner.parent = inner.parent
                i.parent = inner.parent
                p = prop.klass(self, i, **prop.kwargs)
                setattr(self, k, p)

    @classmethod
    def get_argument_names(klass):
        for k in dir(klass):
            attr = getattr(klass, k)
            if isinstance(attr, Property):
                yield k

    def get_argument_values(self):
        """ Return all argument names and values in a dictionary. If an
        argument has no default and has not been set, it's value in the
        dictionary will be None. """

        retval = {}
        for key in self.get_argument_names():
            retval[key] = getattr(self, key, None)

    def register_observer(self, when, resource, policy):
        self.observers[when].append((resource, policy))

    def validate(self, context):
        """ Validate that this resource is correctly specified. Will raise
        an exception if it is invalid. Returns True if it is valid.

        We only validate if:

           - only known arguments are specified
           - the chosen policies all exist, or
           - there is at least one default policy, and
           - the arguments provided conform with all selected policies, and
           - the selected policies all share a single provider

        If the above is all true then we can identify a provider that should
        be able to implement the required policies.

        """

        # This will throw any error if any of our validation fails
        self.get_argument_values()

        # Only allow keys that are in the schema
        for key in self.inner.keys():
            if not key in self.get_argument_names():
                raise error.ParseError(
                    "'%s' is not a valid option for resource %s" % (key, self),
                    self.inner.anchor)

        # Error if doesn't conform to policy
        for p in self.get_potential_policies():
            p.validate(self)

            # throws an exception if there is not oneandonlyone provider
            p.get_provider(context)

        return True

    def test(self, context):
        """ Apply the provider for the selected policy, and then fire any
        events that are being observed. """
        for policy in self.get_potential_policies():
            Provider = policy.get_provider(context)
            p = Provider(self)
            p.test(context)

    def apply(self, context, output=None, policy=None):
        """ Apply the provider for the selected policy, and then fire any
        events that are being observed. """
        if policy is None:
            pol = self.get_default_policy(context)
        else:
            pol_class = self.policies[policy]
            pol = pol_class(self)
        prov_class = pol.get_provider(context)
        prov = prov_class(self)
        changed = prov.apply(context, output)
        context.state.clear_override(self)
        if changed:
            self.fire_event(context, pol.name)
        return changed

    def fire_event(self, context, name):
        """ Apply the appropriate policies on the resources that are observing
        this resource for the firing of a policy. """
        for resource, policy in self.observers[name]:
            context.state.override(resource, policy)

    def bind(self, resources):
        """ Bind this resource to all the resources on which it triggers.
        Returns a list of the resources to which we are bound. """
        bound = []
        policy = self.policy.resolve()
        if policy:
            for trigger in policy.triggers:
                bound.append(trigger.bind(resources, self))
        return bound

    def get_potential_policies(self):
        policy = self.policy.resolve()
        if policy:
            return [P(self) for P in policy.all_potential_policies(self)]
        else:
            return [self.policies.default()(self)]

    def get_default_policy(self, context):
        """ Return an instantiated policy for this resource. """
        selected = context.state.overridden_policy(self)
        if not selected:
            policy = self.policy.resolve()
            if policy:
                selected = policy.literal_policy(self)
            else:
                selected = self.policies.default()
        return selected(self)

    @property
    def id(self):
        classname = getattr(self, '__resource_name__', self.__class__.__name__)
        return "%s[%s]" % (classname, self.inner.name.as_string())

    def __repr__(self):
        return self.id
示例#13
0
文件: file.py 项目: mitchellrj/yaybu
class File(Resource):
    """ A provider for this resource will create or amend an existing file to
    the provided specification.

    For example, the following will create the /etc/hosts file based on a static local file::

        File:
          name: /etc/hosts
          owner: root
          group: root
          mode: 644
          static: my_hosts_file

    The following will create a file using a jinja2 template, and will back up
    the old version of the file if necessary::

        File:
          name: /etc/email_addresses
          owner: root
          group: root
          mode: 644
          template: email_addresses.j2
          template_args:
              foo: [email protected]
              bar: [email protected]
          backup: /etc/email_addresses.{year}-{month}-{day}

    """

    name = Property(FullPath)
    """The full path to the file this resource represents."""

    owner = Property(String, default="root")
    """A unix username or UID who will own created objects. An owner that
    begins with a digit will be interpreted as a UID, otherwise it will be
    looked up using the python 'pwd' module."""

    group = Property(String, default="root")
    """A unix group or GID who will own created objects. A group that begins
    with a digit will be interpreted as a GID, otherwise it will be looked up
    using the python 'grp' module."""

    mode = Property(Octal, default="644")
    """A mode representation as an octal. This can begin with leading zeros if
    you like, but this is not required. DO NOT use yaml Octal representation
    (0o666), this will NOT work."""

    source = Property(File)
    """A file that will be rendered and applied to this resource. """

    renderer = Property(String, default="guess")
    """ How to render the file. 'static' just copies the file, 'jinja2' applies
    a Jinja2 template and 'json' transforms the args dictionary into a JSON
    file """

    args = Property(Dict, default={})
    """ The arguments passed to the renderer."""

    static = Property(File)
    """ DEPRECATED: A static file to copy into this resource. The file is
    located on the yaybu path, so can be colocated with your recipes."""

    template = Property(File)
    """ DEPRECATED: A jinja2 template, used to generate the contents of this
    resource. The template is located on the yaybu path, so can be colocated
    with your recipes"""

    template_args = Property(Dict, default={})
    """ DEPRECATED: The arguments passed to the template."""
    def hash(self, ctx):
        name = self.name.as_string()
        if not ctx.transport.exists(name):
            return ""
        return hashlib.sha1(ctx.transport.get(name)).hexdigest() + \
            str(ctx.transport.stat(name).st_mtime)