implement cdist install
Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
This commit is contained in:
		
					parent
					
						
							
								2c30704ba7
							
						
					
				
			
			
				commit
				
					
						54815e2b29
					
				
			
		
					 7 changed files with 58 additions and 120 deletions
				
			
		| 
						 | 
					@ -158,7 +158,6 @@ class Config(object):
 | 
				
			||||||
        self.local.save_cache()
 | 
					        self.local.save_cache()
 | 
				
			||||||
        self.log.info("Finished successful run in %s seconds", time.time() - start_time)
 | 
					        self.log.info("Finished successful run in %s seconds", time.time() - start_time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def object_list(self):
 | 
					    def object_list(self):
 | 
				
			||||||
        """Short name for object list retrieval"""
 | 
					        """Short name for object list retrieval"""
 | 
				
			||||||
        for cdist_object in core.CdistObject.list_objects(self.local.object_path,
 | 
					        for cdist_object in core.CdistObject.list_objects(self.local.object_path,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,6 +101,11 @@ class CdistType(object):
 | 
				
			||||||
        """Check whether a type is a singleton."""
 | 
					        """Check whether a type is a singleton."""
 | 
				
			||||||
        return os.path.isfile(os.path.join(self.absolute_path, "singleton"))
 | 
					        return os.path.isfile(os.path.join(self.absolute_path, "singleton"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def is_install(self):
 | 
				
			||||||
 | 
					        """Check whether a type is used for installation (if not: for configuration)"""
 | 
				
			||||||
 | 
					        return os.path.isfile(os.path.join(self.absolute_path, "install"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def explorers(self):
 | 
					    def explorers(self):
 | 
				
			||||||
        """Return a list of available explorers"""
 | 
					        """Return a list of available explorers"""
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
# -*- coding: utf-8 -*-
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# 2011-2013 Nico Schottelius (nico-cdist at schottelius.org)
 | 
					# 2011-2013 Nico Schottelius (nico-cdist at schottelius.org)
 | 
				
			||||||
# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
 | 
					# 2012-2013 Steven Armstrong (steven-cdist at armstrong.cc)
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This file is part of cdist.
 | 
					# This file is part of cdist.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								cdist/install.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								cdist/install.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 2013 Steven Armstrong (steven-cdist at armstrong.cc)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This file is part of cdist.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# cdist is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					# it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					# the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					# (at your option) any later version.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# cdist is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					# GNU General Public License for more details.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					# along with cdist. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cdist.config
 | 
				
			||||||
 | 
					import cdist.core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Install(cdist.config.Config):
 | 
				
			||||||
 | 
					    def object_list(self):
 | 
				
			||||||
 | 
					        """Short name for object list retrieval.
 | 
				
			||||||
 | 
					        In install mode, we only care about install objects.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        for cdist_object in cdist.core.CdistObject.list_objects(self.local.object_path,
 | 
				
			||||||
 | 
					                                                         self.local.type_path):
 | 
				
			||||||
 | 
					            if cdist_object.cdist_type.is_install:
 | 
				
			||||||
 | 
					                yield cdist_object
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self.log.debug("Running in install mode, ignoring non install object: {0}".format(cdist_object))
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,16 @@ class TypeTestCase(test.CdistTestCase):
 | 
				
			||||||
        cdist_type = core.CdistType(base_path, '__not_singleton')
 | 
					        cdist_type = core.CdistType(base_path, '__not_singleton')
 | 
				
			||||||
        self.assertFalse(cdist_type.is_singleton)
 | 
					        self.assertFalse(cdist_type.is_singleton)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_install_is_install(self):
 | 
				
			||||||
 | 
					        base_path = fixtures
 | 
				
			||||||
 | 
					        cdist_type = core.CdistType(base_path, '__install')
 | 
				
			||||||
 | 
					        self.assertTrue(cdist_type.is_install)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_not_install_is_install(self):
 | 
				
			||||||
 | 
					        base_path = fixtures
 | 
				
			||||||
 | 
					        cdist_type = core.CdistType(base_path, '__not_install')
 | 
				
			||||||
 | 
					        self.assertFalse(cdist_type.is_install)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_with_explorers(self):
 | 
					    def test_with_explorers(self):
 | 
				
			||||||
        base_path = fixtures
 | 
					        base_path = fixtures
 | 
				
			||||||
        cdist_type = core.CdistType(base_path, '__with_explorers')
 | 
					        cdist_type = core.CdistType(base_path, '__with_explorers')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,118 +0,0 @@
 | 
				
			||||||
autorequire:
 | 
					 | 
				
			||||||
   - objects defined in type manifests should be automatically prerequisites of the current object
 | 
					 | 
				
			||||||
   - __foo/some-id
 | 
					 | 
				
			||||||
      __other other-id --state present
 | 
					 | 
				
			||||||
      => require="__other/other-id" __foo/some-id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
metaparameters:
 | 
					 | 
				
			||||||
   - steal the metaparameters from puppet:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   # I have to be there before the other one
 | 
					 | 
				
			||||||
   __directory /etc/ssh \
 | 
					 | 
				
			||||||
      --before __file/etc/ssh/sshd_config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   # the other one has to be there before me
 | 
					 | 
				
			||||||
   __file /etc/ssh/sshd_config \
 | 
					 | 
				
			||||||
      --after __directory/etc/ssh
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   # if I change, tell the other one about it
 | 
					 | 
				
			||||||
   __file /etc/ssh/sshd_config \
 | 
					 | 
				
			||||||
      --notify __init_script/etc/rc.d/sshd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   # whenever the other one changes, I want to know
 | 
					 | 
				
			||||||
   __init_script /etc/rc.d/sshd \
 | 
					 | 
				
			||||||
      --subscribe __file/etc/ssh/sshd_config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   - how does a type react to a received 'event'?
 | 
					 | 
				
			||||||
      - maybe something like:
 | 
					 | 
				
			||||||
         __some_type/
 | 
					 | 
				
			||||||
            manifest
 | 
					 | 
				
			||||||
            ...
 | 
					 | 
				
			||||||
            gencode-refresh
 | 
					 | 
				
			||||||
            ...
 | 
					 | 
				
			||||||
      - gencode-refresh -> code-refresh -> ssh $target sh -e code-refresh
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
logging:
 | 
					 | 
				
			||||||
   - logging from type emulator without clobbering stdout
 | 
					 | 
				
			||||||
      maybe implement logging server as described here [1]
 | 
					 | 
				
			||||||
   [1] http://docs.python.org/py3k/howto/logging-cookbook.html#configuration-server-example
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   - use different logger to limit output to current area of interest,
 | 
					 | 
				
			||||||
      e.g.
 | 
					 | 
				
			||||||
         explorer.$target_host: explorer related messages for the run for $target_host
 | 
					 | 
				
			||||||
         manifest.$target_host: manifest related messages for the run for $target_host
 | 
					 | 
				
			||||||
         ...
 | 
					 | 
				
			||||||
      then one could filter e.g. on explorer.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   - more granular debug output,
 | 
					 | 
				
			||||||
   [2] http://blog.ooz.ie/2011/03/python-logging-extending-standard.html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tests:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   __init__():
 | 
					 | 
				
			||||||
      - sets up env: __target_host
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   run_initial_manifest():
 | 
					 | 
				
			||||||
      - parameter is actually used (from __init__)
 | 
					 | 
				
			||||||
      - ensure changing the manifest actually runs a different manifest
 | 
					 | 
				
			||||||
      -> give ConfigInstall Constructor different manifest
 | 
					 | 
				
			||||||
         -> different manifest is executed.
 | 
					 | 
				
			||||||
      - test all submitted (from core to type manifest) variables:
 | 
					 | 
				
			||||||
         - ENVIRONMENT
 | 
					 | 
				
			||||||
         - they are set
 | 
					 | 
				
			||||||
         - they contain the correct values
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   run_type_manifest():
 | 
					 | 
				
			||||||
      - test all submitted (from core to type manifest) variables:
 | 
					 | 
				
			||||||
         - ENVIRONMENT
 | 
					 | 
				
			||||||
         - they are set
 | 
					 | 
				
			||||||
         - they contain the correct values
 | 
					 | 
				
			||||||
      - same tests as for test_initial_manifest_*?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   run_manifest():
 | 
					 | 
				
			||||||
      - test all submitted variables:
 | 
					 | 
				
			||||||
         - ENVIRONMENT
 | 
					 | 
				
			||||||
            - including __debug, if debug
 | 
					 | 
				
			||||||
         - they are set
 | 
					 | 
				
			||||||
         - they contain the correct values
 | 
					 | 
				
			||||||
      - does $require work?
 | 
					 | 
				
			||||||
      - check that exception raised, if manifest is not existent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   object_run():
 | 
					 | 
				
			||||||
      - ensure no object is run twice
 | 
					 | 
				
			||||||
      - ensure requirements are taken into account?
 | 
					 | 
				
			||||||
         - and order of run is adjusted
 | 
					 | 
				
			||||||
      - check (from extern?) that all needed variables are setup
 | 
					 | 
				
			||||||
      - ensure no code-{local, remote} is created, 
 | 
					 | 
				
			||||||
         if gencode is not producing code
 | 
					 | 
				
			||||||
      - ensure THAT code-{local, remote} contains what gencode created
 | 
					 | 
				
			||||||
      - abort if gencode-* fails
 | 
					 | 
				
			||||||
      - abort if code-* fails
 | 
					 | 
				
			||||||
         - abort == raise(FooException)
 | 
					 | 
				
			||||||
      - gencode-*: ensure ENVIRONMENT is setup correctly
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   run_type_explorer()
 | 
					 | 
				
			||||||
      - ensure ALL type explores have been run
 | 
					 | 
				
			||||||
      - ensure output is saved to correct path
 | 
					 | 
				
			||||||
      - ensure a type with {0,1,2} explorers works ?
 | 
					 | 
				
			||||||
         - none, one, multiple
 | 
					 | 
				
			||||||
      - ensure ENVIRONMENT is setup correctly
 | 
					 | 
				
			||||||
      - fails if ANY of the given explorer fails
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   run_global_explorers():
 | 
					 | 
				
			||||||
      - ensure ALL type explores have been run
 | 
					 | 
				
			||||||
      - ensure output is saved to correct path
 | 
					 | 
				
			||||||
      - ensure a type with {0,1,2} explorers works ?
 | 
					 | 
				
			||||||
         - none, one, multiple
 | 
					 | 
				
			||||||
      - ensure ENVIRONMENT is setup correctly
 | 
					 | 
				
			||||||
      - fails if ANY of the given explorer fails
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
Code fixes needed:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   - shutil, os.mkdir, etc. everywhere: catch/reraise exceptions correctly
 | 
					 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ def commandline():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    import cdist.banner
 | 
					    import cdist.banner
 | 
				
			||||||
    import cdist.config
 | 
					    import cdist.config
 | 
				
			||||||
 | 
					    import cdist.install
 | 
				
			||||||
    import cdist.shell
 | 
					    import cdist.shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Construct parser others can reuse
 | 
					    # Construct parser others can reuse
 | 
				
			||||||
| 
						 | 
					@ -90,6 +91,10 @@ def commandline():
 | 
				
			||||||
         help='Select shell to use, defaults to current shell')
 | 
					         help='Select shell to use, defaults to current shell')
 | 
				
			||||||
    parser['shell'].set_defaults(func=cdist.shell.Shell.commandline)
 | 
					    parser['shell'].set_defaults(func=cdist.shell.Shell.commandline)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Install
 | 
				
			||||||
 | 
					    parser['install'] = parser['sub'].add_parser('install',
 | 
				
			||||||
 | 
					        parents=[parser['loglevel'], parser['config']])
 | 
				
			||||||
 | 
					    parser['install'].set_defaults(func=cdist.install.Install.commandline)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for p in parser:
 | 
					    for p in parser:
 | 
				
			||||||
        parser[p].epilog = "Get cdist at http://www.nico.schottelius.org/software/cdist/"
 | 
					        parser[p].epilog = "Get cdist at http://www.nico.schottelius.org/software/cdist/"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue