Beispiel #1
0
class Kitchen(Environment):
    
    def __init__(self):
        self._running = False
        super(Kitchen, self).__init__()
    
    def reset(self):
        super(Kitchen, self).reset()
        
        if hasattr(self, '_running') and self._running:
            raise Fail("Error can't reset Kitchen while it is running")
        
        self._sourced_recipes  = set()
        self._included_recipes = OrderedDict()
        self.cookbooks = AttributeDict()
        self._cookbookPaths = [ ]
        self._running = False
    
    def run(self):
        recipes = ""
        
        for k, v in self._included_recipes.iteritems():
            name = k
            (cookbook, recipe) = v
            
            recipes += "%s : %s(%s); " % (name, cookbook, recipe)
        
        utils.log("Kitchen is up and running...")
        utils.log("   recipes       (%d): %s" % (len(self._included_recipes), recipes))
        utils.log("   cookbook_path (%d): %s" % (len(self._cookbookPaths), str(self._cookbookPaths)))
        
        self._running = True
        self._preRun()
        
        super(Kitchen, self).run()
        
        self._postRun()
        self._running = False
        
        utils.log("Kitchen finished processing all recipes successfully!")
    
    def includeRecipe(self, *args):
        for name in args:
            if name in self._included_recipes:
                continue
            
            try:
                cookbook, recipe = name.split('.')
            except ValueError:
                cookbook, recipe = name, "default"
            
            try:
                cookbook = self.cookbooks[cookbook]
            except KeyError:
                try:
                    self._loadCookbook(cookbook)
                    cookbook = self.cookbooks[cookbook]
                except ImportError:
                    utils.log("Error: unable to find cookbook for recipe '%s'" % name)
                    raise
            
            self._included_recipes[name] = (cookbook, recipe)
            
            if self._running:
                self._sourceRecipe(cookbook, recipe)
    
    def addCookbookPath(self, *args):
        for origPath in args:
            path = utils.resolvePath(origPath)
            #print "%s vs %s" % (origPath, path)
            
            self._cookbookPaths.append((origPath, path))
    
    def _registerCookbook(self, cookbook):
        #utils.log("Registering cookbook %s" % (cookbook, ))
        self.updateConfig(dict((k, v.get('default')) for k, v in cookbook.config.items()), False)
        self.cookbooks[cookbook.name] = cookbook
    
    def _loadCookbook(self, *args, **kwargs):
        for name in args:
            cookbook = None
            
            for origpath, path in reversed(self._cookbookPaths):
                fullpath = os.path.join(path, name)
                if not os.path.exists(fullpath):
                    continue
                
                cookbook = Cookbook.loadFromPath(name, fullpath)
                break
            
            if not cookbook:
                raise ImportError("Cookbook '%s' not found" % name)
            
            self._registerCookbook(cookbook)
    
    def _sourceRecipe(self, cookbook, recipe):
        name = "%s.%s" % (cookbook.name, recipe)
        if name in self._sourced_recipes:
            return
        
        utils.log("Sourcing recipe '%s' in cookbook '%s'" % (recipe, cookbook.name))
        
        self._sourced_recipes.add(name)
        cookbook.loader(self)
        
        rc = cookbook.getRecipe(recipe)
        globs = { 'env': self }
        
        with self:
            exec compile(rc, name, 'exec') in globs
    
    def _preRun(self):
        for name in self._included_recipes:
            (cookbook, recipe) = self._included_recipes[name]
            self._sourceRecipe(cookbook, recipe)
    
    def _postRun(self):
        pass
    
    def __getstate__(self):
        state = super(Kitchen, self).__getstate__()
        
        state.update(
            cookbookPaths   = [ x[0] for x in self.cookbookPaths ],
            includedRecipes = self.includedRecipes, 
        )
        
        return state
    
    def __setstate__(self, state):
        super(Kitchen, self).__setstate__(state)
        
        for path in state['cookbookPaths']:
            self.addCookbookPath(path)
        
        for recipe in state['includedRecipes']:
            self.includeRecipe(recipe)