Example #1
0
    def __init__(self, name=None, commit=None, create=False):
        """
        Construct a blueprint in the new format in a backwards-compatible
        manner.
        """
        self.name = name
        self._commit = commit

        # Create a new blueprint object and populate it based on this server.
        if create:
            super(Blueprint, self).__init__()
            import backend
            for funcname in backend.__all__:
                getattr(backend, funcname)(self)
            import services
            services.services(self)

        # Create a blueprint from a Git repository.
        elif name is not None:
            git.init()
            if self._commit is None:
                self._commit = git.rev_parse('refs/heads/{0}'.format(name))
                if self._commit is None:
                    raise NotFoundError(name)
            tree = git.tree(self._commit)
            blob = git.blob(tree, 'blueprint.json')
            content = git.content(blob)
            super(Blueprint, self).__init__(**json.loads(content))

        # Create an empty blueprint object to be filled in later.
        else:
            super(Blueprint, self).__init__()
Example #2
0
    def __init__(self, name=None, commit=None, create=False):
        """
        Construct a blueprint in the new format in a backwards-compatible
        manner.
        """
        self.name = name
        self._commit = commit

        # Create a new blueprint object and populate it based on this server.
        if create:
            super(Blueprint, self).__init__()
            for funcname in backend.__all__:
                getattr(backend, funcname)(self)

        # Create a blueprint from a Git repository.
        elif name is not None:
            git.init()
            if self._commit is None:
                self._commit = git.rev_parse('refs/heads/%s' % (name))
                if self._commit is None:
                    raise KeyError(name)
            tree = git.tree(self._commit)
            blob = git.blob(tree, 'blueprint.json')
            content = git.content(blob)
            super(Blueprint, self).__init__(**json.loads(content))

        # Create an empty blueprint object to be filled in later.
        else:
            super(Blueprint, self).__init__()
Example #3
0
    def sh(self):
        """
        Generate shell code.
        """
        s = sh.Script(self.name, comment=self.DISCLAIMER)

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            s.add('tar xf "{0}" -C "{1}"',
                  filename,
                  dirname,
                  sources={filename: content})

        # Place files.
        for pathname, f in sorted(self.files.iteritems()):
            s.add('mkdir -p "{0}"', os.path.dirname(pathname))
            if '120000' == f['mode'] or '120777' == f['mode']:
                s.add('ln -s "{0}" "{1}"', f['content'], pathname)
                continue
            command = 'cat'
            if 'base64' == f['encoding']:
                command = 'base64 --decode'
            eof = 'EOF'
            while re.search(r'{0}'.format(eof), f['content']):
                eof += 'EOF'
            s.add('{0} >"{1}" <<{2}', command, pathname, eof)
            s.add(raw=f['content'])
            if 0 < len(f['content']) and '\n' != f['content'][-1]:
                eof = '\n{0}'.format(eof)
            s.add(eof)
            if 'root' != f['owner']:
                s.add('chown {0} "{1}"', f['owner'], pathname)
            if 'root' != f['group']:
                s.add('chgrp {0} "{1}"', f['group'], pathname)
            if '000644' != f['mode']:
                s.add('chmod {0} "{1}"', f['mode'][-4:], pathname)

        # Install packages.
        def before(manager):
            if 'apt' == manager.name:
                s.add('apt-get -q update')

        def package(manager, package, version):
            if manager.name == package:
                return
            s.add(manager(package, version))
            match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
            if 'apt' != manager.name:
                return
            if match is not None and rubygems_update():
                s.add('/usr/bin/gem{0} install --no-rdoc --no-ri '
                  'rubygems-update', match.group(1))
                s.add('/usr/bin/ruby{0} $(PATH=$PATH:/var/lib/gems/{0}/bin '
                  'which update_rubygems)', match.group(1))
        self.walk(before=before, package=package)

        return s
Example #4
0
            def gen_content():

                # It's a good thing `gen_content` is never called by the
                # `Blueprint.__init__` callbacks, since this would always
                # raise `AttributeError` on the fake blueprint structure
                # used to initialize a real `Blueprint` object.
                tree = git.tree(b._commit)

                blob = git.blob(tree, filename)
                return git.content(blob)
Example #5
0
 def checkout(cls, name, commit=None):
     git.init()
     if commit is None:
         commit = git.rev_parse('refs/heads/{0}'.format(name))
         if commit is None:
             raise NotFoundError(name)
     tree = git.tree(commit)
     blob = git.blob(tree, 'blueprint.json')
     content = git.content(blob)
     return cls(name, commit, **json.loads(content))
            def gen_content():

                # It's a good thing `gen_content` is never called by the
                # `Blueprint.__init__` callbacks, since this would always
                # raise `AttributeError` on the fake blueprint structure
                # used to initialize a real `Blueprint` object.
                tree = git.tree(b._commit)

                blob = git.blob(tree, filename)
                return git.content(blob)
Example #7
0
 def blueprintignore(self):
     """
     Return the blueprint's ~/.blueprintignore file.  Prior to v3.0.4
     this file was stored as .gitignore in the repository.
     """
     tree = git.tree(self._commit)
     blob = git.blob(tree, '.blueprintignore')
     if blob is None:
         blob = git.blob(tree, '.gitignore')
     import ignore
     if blob is None:
         return ignore.Rules('')
     content = git.content(blob)
     if content is None:
         return ignore.Rules('')
     return ignore.Rules(content)
Example #8
0
 def blueprintignore(self):
     """
     Return the blueprint's blueprintignore file.  Prior to v3.0.9 this
     file was stored as .blueprintignore in the repository.  Prior to
     v3.0.4 this file was stored as .gitignore in the repository.
     """
     tree = git.tree(self._commit)
     blob = git.blob(tree, 'blueprintignore')
     if blob is None:
         blob = git.blob(tree, '.blueprintignore')
     if blob is None:
         blob = git.blob(tree, '.gitignore')
     import ignore
     if blob is None:
         return ignore.Rules('')
     content = git.content(blob)
     if content is None:
         return ignore.Rules('')
     return ignore.Rules(content)
Example #9
0
 def gen_content():
     tree = git.tree(self._commit)
     blob = git.blob(tree, filename)
     return git.content(blob)
Example #10
0
    def chef(self):
        """
        Generate Chef code.
        """
        c = chef.Cookbook(self.name, comment=self.DISCLAIMER)

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            pathname = os.path.join('/tmp', filename)
            c.file(pathname,
                   content,
                   owner='root',
                   group='root',
                   mode='0644',
                   backup=False,
                   source=pathname[1:])
            c.execute('tar xf {0}'.format(pathname), cwd=dirname)

        # Place files.
        for pathname, f in sorted(self.files.iteritems()):
            c.directory(os.path.dirname(pathname),
                        group='root',
                        mode='755',
                        owner='root',
                        recursive=True)
            if '120000' == f['mode'] or '120777' == f['mode']:
                c.link(pathname,
                       owner=f['owner'],
                       group=f['group'],
                       to=f['content'])
                continue
            content = f['content']
            if 'base64' == f['encoding']:
                content = base64.b64decode(content)
            c.file(pathname, content,
                   owner=f['owner'],
                   group=f['group'],
                   mode=f['mode'][-4:],
                   backup=False,
                   source=pathname[1:])

        # Install packages.
        def before(manager):
            if 'apt' == manager.name:
                c.execute('apt-get -q update')
        def package(manager, package, version):
            if manager.name == package:
                return

            if 'apt' == manager.name:
                c.apt_package(package, version=version)
                match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
                if match is not None and rubygems_update():
                    c.execute('/usr/bin/gem{0} install --no-rdoc --no-ri '
                              'rubygems-update'.format(match.group(1)))
                    c.execute('/usr/bin/ruby{0} '
                              '$(PATH=$PATH:/var/lib/gems/{0}/bin '
                              'which update_rubygems)"'.format(match.group(1)))

            # All types of gems get to have package resources.
            elif re.search(r'ruby', manager.name) is not None:
                match = re.match(r'^ruby(?:gems)?(\d+\.\d+(?:\.\d+)?)',
                                 manager.name)
                c.gem_package(package,
                    gem_binary='/usr/bin/gem{0}'.format(match.group(1)),
                    version=version)

            # Everything else is an execute resource.
            else:
                c.execute(manager(package, version))

        self.walk(before=before, package=package)

        return c
Example #11
0
    def puppet(self):
        """
        Generate Puppet code.
        """
        m = puppet.Manifest(self.name, comment=self.DISCLAIMER)

        # Set the default `PATH` for exec resources.
        m.add(puppet.Exec.defaults(path=os.environ['PATH']))

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            pathname = os.path.join('/tmp', filename)
            m['sources'].add(puppet.File(
                pathname,
                self.name,
                content,
                owner='root',
                group='root',
                mode='0644',
                source='puppet:///{0}/{1}'.format(self.name,
                                                  pathname[1:])))
            m['sources'].add(puppet.Exec(
                'tar xf {0}'.format(pathname),
                cwd=dirname,
                require=puppet.File.ref(pathname)))

        # Place files.
        if 0 < len(self.files):
            for pathname, f in sorted(self.files.iteritems()):

                # Create resources for parent directories and let the
                # autorequire mechanism work out dependencies.
                dirnames = os.path.dirname(pathname).split('/')[1:]
                for i in xrange(len(dirnames)):
                    m['files'].add(puppet.File(
                        os.path.join('/', *dirnames[0:i+1]),
                        ensure='directory'))

                # Create the actual file resource.
                if '120000' == f['mode'] or '120777' == f['mode']:
                    m['files'].add(puppet.File(pathname,
                                               None,
                                               None,
                                               owner=f['owner'],
                                               group=f['group'],
                                               ensure=f['content']))
                    continue
                content = f['content']
                if 'base64' == f['encoding']:
                    content = base64.b64decode(content)
                m['files'].add(puppet.File(pathname,
                                           self.name,
                                           content,
                                           owner=f['owner'],
                                           group=f['group'],
                                           mode=f['mode'][-4:],
                                           ensure='file'))

        # Install packages.
        deps = []
        def before(manager):
            deps.append(manager)
            if 'apt' != manager.name:
                return
            if 0 == len(manager):
                return
            if 1 == len(manager) and manager.name in manager:
                return
            m['packages'].add(puppet.Exec('apt-get -q update',
                                          before=puppet.Class.ref('apt')))
        def package(manager, package, version):

            # `apt` is easy since it's the default.
            if 'apt' == manager.name:
                m['packages'][manager].add(puppet.Package(package,
                                                          ensure=version))

                # If APT is installing RubyGems, get complicated.
                match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
                if match is not None and rubygems_update():
                    m['packages'][manager].add(puppet.Exec('/bin/sh -c "'
                        '/usr/bin/gem{0} install --no-rdoc --no-ri '
                        'rubygems-update; '
                        '/usr/bin/ruby{0} $(PATH=$PATH:/var/lib/gems/{0}/bin '
                        'which update_rubygems)"'.format(match.group(1)),
                        require=puppet.Package.ref(package)))

            # RubyGems for Ruby 1.8 is easy, too, because Puppet has a
            # built in provider.
            elif 'rubygems1.8' == manager.name:
                m['packages'][manager].add(puppet.Package(package,
                    ensure=version,
                    provider='gem'))

            # Other versions of RubyGems are slightly more complicated.
            elif re.search(r'ruby', manager.name) is not None:
                match = re.match(r'^ruby(?:gems)?(\d+\.\d+(?:\.\d+)?)',
                                 manager.name)
                m['packages'][manager].add(puppet.Exec(
                    manager(package, version),
                    creates='{0}/{1}/gems/{2}-{3}'.format(rubygems_path(),
                                                          match.group(1),
                                                          package,
                                                          version)))

            # Python works basically like alternative versions of Ruby
            # but follows a less predictable directory structure so the
            # directory is not known ahead of time.  This just so happens
            # to be the way everything else works, too.
            else:
                m['packages'][manager].add(puppet.Exec(
                    manager(package, version)))

        self.walk(before=before, package=package)
        m['packages'].dep(*[puppet.Class.ref(dep) for dep in deps])

        # Strict ordering of classes.
        deps = []
        if 0 < len(self.sources):
            deps.append('sources')
        if 0 < len(self.files):
            deps.append('files')
        if 0 < len(self.packages):
            deps.append('packages')
        m.dep(*[puppet.Class.ref(dep) for dep in deps])

        return m
Example #12
0
    def sh(self):
        """
        Generate shell code.
        """
        s = sh.Script(self.name, comment=self.DISCLAIMER)

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            s.add('tar xf "%s" -C "%s"' % filename,
                  dirname,
                  sources={filename: content})

        # Place files.
        for pathname, f in sorted(self.files.iteritems()):
            s.add('mkdir -p "%s"' % os.path.dirname(pathname))
            if '120000' == f['mode'] or '120777' == f['mode']:
                s.add('ln -s "%s" "%s"' % (f['content'], pathname))
                continue
            command = 'cat'
            if 'base64' == f['encoding']:
                command = 'base64 --decode'
            eof = 'EOF'
            while re.search(r'%s' % (eof), f['content']):
                eof += 'EOF'
            s.add('%s >"%s" <<%s' % (command, pathname, eof))
            s.add(raw=f['content'])
            if 0 < len(f['content']) and '\n' != f['content'][-1]:
                eof = '\n%s' % (eof)
            s.add(eof)
            if 'root' != f['owner']:
                s.add('chown %s "%s"' % (f['owner'], pathname))
            if 'root' != f['group']:
                s.add('chgrp %s "%s"' % (f['group'], pathname))
            if '000644' != f['mode']:
                s.add('chmod %s "%s"' % (f['mode'][-4:], pathname))

        # Install packages.
        def before(manager):
            if 'apt' == manager.name and not is_rpmpkgmgr():
                s.add('apt-get -q update')
            elif 'rpm' == manager.name and is_rpmpkgmgr():
                s.add('yum clean expire-cache')

        def package(manager, package, version):
            if manager.name == package:
                return
            s.add(manager(package, version))
            match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
            if 'apt' != manager.name and 'rpm' != manager.name:
                return
            if match is not None and rubygems_update():
                s.add('/usr/bin/gem%s install --no-rdoc --no-ri '
                      'rubygems-update' % match.group(1))
                s.add('/usr/bin/ruby%s $(PATH=$PATH:/var/lib/gems/%s/bin '
                      'which update_rubygems)' % match.group(1))

        self.walk(before=before, package=package)

        return s
Example #13
0
    def chef(self):
        """
        Generate Chef code.
        """
        c = chef.Cookbook(self.name, comment=self.DISCLAIMER)

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            pathname = os.path.join('/tmp', filename)
            c.file(pathname,
                   content,
                   owner='root',
                   group='root',
                   mode='0644',
                   backup=False,
                   source=pathname[1:])
            c.execute('tar xf %s' % (pathname), cwd=dirname)

        # Place files.
        for pathname, f in sorted(self.files.iteritems()):
            c.directory(os.path.dirname(pathname),
                        group='root',
                        mode='0755',
                        owner='root',
                        recursive=True)
            if '120000' == f['mode'] or '120777' == f['mode']:
                c.link(pathname,
                       owner=f['owner'],
                       group=f['group'],
                       to=f['content'])
                continue
            content = f['content']
            if 'base64' == f['encoding']:
                content = base64.b64decode(content)
            c.file(pathname,
                   content,
                   owner=f['owner'],
                   group=f['group'],
                   mode=f['mode'][-4:],
                   backup=False,
                   source=pathname[1:])

        # Install packages.
        def before(manager):
            if 'apt' == manager.name:
                c.execute('apt-get -q update')

        def package(manager, package, version):
            if manager.name == package:
                return

            if 'apt' == manager.name:
                c.apt_package(package, version=version)
                match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
                if match is not None and rubygems_update():
                    c.execute('/usr/bin/gem%s install --no-rdoc --no-ri '
                              'rubygems-update' % (match.group(1)))
                    c.execute('/usr/bin/ruby%s '
                              '$(PATH=$PATH:/var/lib/gems/%s/bin '
                              'which update_rubygems)"' % (match.group(1)))

            # All types of gems get to have package resources.
            elif re.search(r'ruby', manager.name) is not None:
                match = re.match(r'^ruby(?:gems)?(\d+\.\d+(?:\.\d+)?)',
                                 manager.name)
                c.gem_package(package,
                              gem_binary='/usr/bin/gem%s' % (match.group(1)),
                              version=version)

            # Everything else is an execute resource.
            else:
                c.execute(manager(package, version))

        self.walk(before=before, package=package)

        return c
Example #14
0
    def puppet(self):
        """
        Generate Puppet code.
        """
        m = puppet.Manifest(self.name, comment=self.DISCLAIMER)

        # Set the default `PATH` for exec resources.
        m.add(puppet.Exec.defaults(path=os.environ['PATH']))

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            pathname = os.path.join('/tmp', filename)
            m['sources'].add(
                puppet.File(pathname,
                            self.name,
                            content,
                            owner='root',
                            group='root',
                            mode='0644',
                            source='puppet:///%s/%s' %
                            (self.name, pathname[1:])))
            m['sources'].add(
                puppet.Exec('tar xf %s' % (pathname),
                            cwd=dirname,
                            require=puppet.File.ref(pathname)))

        # Place files.
        if 0 < len(self.files):
            for pathname, f in sorted(self.files.iteritems()):

                # Create resources for parent directories and let the
                # autorequire mechanism work out dependencies.
                dirnames = os.path.dirname(pathname).split('/')[1:]
                for i in xrange(len(dirnames)):
                    m['files'].add(
                        puppet.File(os.path.join('/', *dirnames[0:i + 1]),
                                    ensure='directory'))

                # Create the actual file resource.
                if '120000' == f['mode'] or '120777' == f['mode']:
                    m['files'].add(
                        puppet.File(pathname,
                                    None,
                                    None,
                                    owner=f['owner'],
                                    group=f['group'],
                                    ensure=f['content']))
                    continue
                content = f['content']
                if 'base64' == f['encoding']:
                    content = base64.b64decode(content)
                m['files'].add(
                    puppet.File(pathname,
                                self.name,
                                content,
                                owner=f['owner'],
                                group=f['group'],
                                mode=f['mode'][-4:],
                                ensure='file'))

        # Install packages.
        deps = []

        def before(manager):
            deps.append(manager)
            if 'apt' != manager.name:
                return
            if 0 == len(manager):
                return
            if 1 == len(manager) and manager.name in manager:
                return
            m['packages'].add(
                puppet.Exec('apt-get -q update',
                            before=puppet.Class.ref('apt')))

        def package(manager, package, version):
            # `apt` is easy since it's the default.
            if 'apt' == manager.name or 'rpm' == manager.name:
                m['packages'][manager].add(
                    puppet.Package(package, ensure=version))

                # If APT is installing RubyGems, get complicated.
                match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
                if match is not None and rubygems_update():
                    m['packages'][manager].add(
                        puppet.Exec(
                            '/bin/sh -c "'
                            '/usr/bin/gem%s install --no-rdoc --no-ri '
                            'rubygems-update; '
                            '/usr/bin/ruby%s $(PATH=$PATH:/var/lib/gems/%s/bin '
                            'which update_rubygems)"' % (match.group(1)),
                            require=puppet.Package.ref(package)))

            # RubyGems for Ruby 1.8 is easy, too, because Puppet has a
            # built in provider.
            elif 'rubygems1.8' == manager.name or 'rubygems' == manager.name:
                m['packages'][manager].add(
                    puppet.Package(package, ensure=version, provider='gem'))

            # Other versions of RubyGems are slightly more complicated.
            elif re.search(r'ruby', manager.name) is not None:
                match = re.match(r'^ruby(?:gems)?(\d+\.\d+(?:\.\d+)?)',
                                 manager.name)
                m['packages'][manager].add(
                    puppet.Exec(
                        manager(package, version),
                        creates='%s/%s/gems/%s-%s' %
                        (rubygems_path(), match.group(1), package, version)))

            # Python works basically like alternative versions of Ruby
            # but follows a less predictable directory structure so the
            # directory is not known ahead of time.  This just so happens
            # to be the way everything else works, too.
            else:
                m['packages'][manager].add(
                    puppet.Exec(manager(package, version)))

        self.walk(before=before, package=package)
        m['packages'].dep(*[puppet.Class.ref(dep) for dep in deps])

        # Strict ordering of classes.
        deps = []
        if 0 < len(self.sources):
            deps.append('sources')
        if 0 < len(self.files):
            deps.append('files')
        if 0 < len(self.packages):
            deps.append('packages')
        m.dep(*[puppet.Class.ref(dep) for dep in deps])

        return m
Example #15
0
    def sh(self, server='https://devstructure.com', secret=None):
        """
        Generate shell code.
        """
        import sh
        s = sh.Script(self.name, comment=self.DISCLAIMER)

        # Extract source tarballs.
        if secret is not None:
            for dirname, filename in sorted(self.sources.iteritems()):
                s.add('wget "{0}/{1}/{2}/{3}"',
                      server,
                      secret,
                      self.name,
                      filename)
                s.add('tar xf "{0}" -C "{1}"',
                      filename,
                      dirname)
        else:
            tree = git.tree(self._commit)
            for dirname, filename in sorted(self.sources.iteritems()):
                blob = git.blob(tree, filename)
                content = git.content(blob)
                s.add('tar xf "{0}" -C "{1}"',
                      filename,
                      dirname,
                      sources={filename: content})

        # Place files.
        for pathname, f in sorted(self.files.iteritems()):
            s.add('mkdir -p "{0}"', os.path.dirname(pathname))
            if '120000' == f['mode'] or '120777' == f['mode']:
                s.add('ln -s "{0}" "{1}"', f['content'], pathname)
                continue
            command = 'cat'
            if 'base64' == f['encoding']:
                command = 'base64 --decode'
            eof = 'EOF'
            while re.search(r'{0}'.format(eof), f['content']):
                eof += 'EOF'
            s.add('{0} >"{1}" <<{2}', command, pathname, eof)
            s.add(raw=f['content'])
            if 0 < len(f['content']) and '\n' != f['content'][-1]:
                eof = '\n{0}'.format(eof)
            s.add(eof)
            if 'root' != f['owner']:
                s.add('chown {0} "{1}"', f['owner'], pathname)
            if 'root' != f['group']:
                s.add('chgrp {0} "{1}"', f['group'], pathname)
            if '000644' != f['mode']:
                s.add('chmod {0} "{1}"', f['mode'][-4:], pathname)

        # Install packages.
        def before(manager):
            if 0 == len(manager):
                return
            if 'apt' == manager.name:
                s.add('export APT_LISTBUGS_FRONTEND="none"')
                s.add('export APT_LISTCHANGES_FRONTEND="none"')
                s.add('export DEBIAN_FRONTEND="noninteractive"')
                s.add('apt-get -q update')
            elif 'yum' == manager.name:
                s.add('yum makecache')

        def package(manager, package, version):
            if manager.name == package:
                return
            s.add(manager(package, version))
            if manager.name not in ('apt', 'yum'):
                return

            # See comments on this section in `puppet` above.
            match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
            if match is not None and util.rubygems_update():
                s.add('/usr/bin/gem{0} install --no-rdoc --no-ri '
                  'rubygems-update', match.group(1))
                s.add('/usr/bin/ruby{0} $(PATH=$PATH:/var/lib/gems/{0}/bin '
                  'which update_rubygems)', match.group(1))

        self.walk(before=before, package=package)

        return s
Example #16
0
    def sh(self):
        """
        Generate shell code.
        """
        s = sh.Script(self.name, comment=self.DISCLAIMER)

        # Extract source tarballs.
        tree = git.tree(self._commit)
        for dirname, filename in sorted(self.sources.iteritems()):
            blob = git.blob(tree, filename)
            content = git.content(blob)
            s.add('tar xf "{0}" -C "{1}"',
                  filename,
                  dirname,
                  sources={filename: content})

        # Place files.
        for pathname, f in sorted(self.files.iteritems()):
            s.add('mkdir -p "{0}"', os.path.dirname(pathname))
            if '120000' == f['mode'] or '120777' == f['mode']:
                s.add('ln -s "{0}" "{1}"', f['content'], pathname)
                continue
            command = 'cat'
            if 'base64' == f['encoding']:
                command = 'base64 --decode'
            eof = 'EOF'
            while re.search(r'{0}'.format(eof), f['content']):
                eof += 'EOF'
            s.add('{0} >"{1}" <<{2}', command, pathname, eof)
            s.add(raw=f['content'])
            if 0 < len(f['content']) and '\n' != f['content'][-1]:
                eof = '\n{0}'.format(eof)
            s.add(eof)
            if 'root' != f['owner']:
                s.add('chown {0} "{1}"', f['owner'], pathname)
            if 'root' != f['group']:
                s.add('chgrp {0} "{1}"', f['group'], pathname)
            if '000644' != f['mode']:
                s.add('chmod {0} "{1}"', f['mode'][-4:], pathname)

        # Install packages.
        def before(manager):
            if 0 == len(manager):
                return
            if 'apt' == manager.name:
                s.add('apt-get -q update')
            elif 'yum' == manager.name:
                s.add('yum makecache')

        def package(manager, package, version):
            if manager.name == package:
                return
            s.add(manager(package, version))
            if manager.name not in ('apt', 'yum'):
                return

            # See comments on this section in `puppet` above.
            match = re.match(r'^rubygems(\d+\.\d+(?:\.\d+)?)$', package)
            if match is not None and rubygems_update():
                s.add(
                    '/usr/bin/gem{0} install --no-rdoc --no-ri '
                    'rubygems-update', match.group(1))
                s.add(
                    '/usr/bin/ruby{0} $(PATH=$PATH:/var/lib/gems/{0}/bin '
                    'which update_rubygems)', match.group(1))

        self.walk(before=before, package=package)

        return s