move out banner, fail at emulator

Signed-off-by: Nico Schottelius <nico@kr.ethz.ch>
This commit is contained in:
Nico Schottelius 2011-09-26 11:05:18 +02:00
parent cf920ca3e9
commit 16d58dcac7
5 changed files with 140 additions and 122 deletions

204
bin/cdist
View file

@ -32,40 +32,7 @@ import stat
import sys import sys
import tempfile import tempfile
log = logging.getLogger(__name__)
BANNER = """
.. . .x+=:. s
dF @88> z` ^% :8
'88bu. %8P . <k .88
. '*88888bu . .@8Ned8" :888ooo
.udR88N ^"*8888N .@88u .@^%8888" -*8888888
<888'888k beWE "888L ''888E` x88: `)8b. 8888
9888 'Y" 888E 888E 888E 8888N=*8888 8888
9888 888E 888E 888E %8" R88 8888
9888 888E 888F 888E @8Wou 9% .8888Lu=
?8888u../ .888N..888 888& .888888P` ^%888*
"8888P' `"888*"" R888" ` ^"F 'Y"
"P' "" ""
"""
VERSION = "2.0.1"
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
log = logging.getLogger()
def file_to_list(filename):
"""Return list from \n seperated file"""
if os.path.isfile(filename):
file_fd = open(filename, "r")
lines = file_fd.readlines()
file_fd.close()
# Remove \n from all lines
lines = map(lambda s: s.strip(), lines)
else:
lines = []
return lines
class Cdist: class Cdist:
"""Cdist main class to hold arbitrary data""" """Cdist main class to hold arbitrary data"""
@ -73,20 +40,22 @@ class Cdist:
def __init__(self, target_host, def __init__(self, target_host,
initial_manifest=False, remote_user="root", initial_manifest=False, remote_user="root",
home=None, debug=False): home=None, debug=False):
self.target_host = target_host
self.path = cdist.path.Path(target_host, self.target_host = target_host
self.debug = debug
self.remote_user = remote_user
self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
self.path = cdist.path.Path(self.target_host,
initial_manifest=initial_manifest, initial_manifest=initial_manifest,
remote_user=remote_user, remote_user=self.remote_user,
remote_prefix=self.remote_prefix,
base_dir=home, base_dir=home,
debug=debug) debug=debug)
self.debug = debug
self.objects_prepared = [] self.objects_prepared = []
self.remote_user = remote_user
def cleanup(self): def cleanup(self):
self.path.cleanup() self.path.cleanup()
@ -94,71 +63,69 @@ class Cdist:
"""Run global explorers""" """Run global explorers"""
explorers = self.path.list_global_explorers() explorers = self.path.list_global_explorers()
if(len(explorers) == 0): if(len(explorers) == 0):
raise CdistError("No explorers found in", self.global_explorer_dir) raise CdistError("No explorers found in", self.path.global_explorer_dir)
self.transfer_global_explorers() self.path.transfer_global_explorers()
for explorer in explorers: for explorer in explorers:
output = self.global_explorer_output_path(explorer) output = self.path.global_explorer_output_path(explorer)
output_fd = open(output, mode='w') output_fd = open(output, mode='w')
cmd = [] cmd = []
cmd.append("__explorer=" + REMOTE_GLOBAL_EXPLORER_DIR) cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
cmd.append(self.remote_global_explorer_path(explorer)) cmd.append(self.path.remote_global_explorer_path(explorer))
self.run_or_fail(cmd, stdout=output_fd, remote=True) cdist.exec.run_or_fail(cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
output_fd.close() output_fd.close()
def run_type_explorer(self, cdist_object): def run_type_explorer(self, cdist_object):
"""Run type specific explorers for objects""" """Run type specific explorers for objects"""
# Based on bin/cdist-object-explorer-run
# Transfering explorers for this type type = self.path.get_type_from_object(cdist_object)
type = self.get_type_from_object(cdist_object) self.path.transfer_type_explorers(type)
self.transfer_type_explorers(type)
cmd = [] cmd = []
cmd.append("__explorer=" + REMOTE_GLOBAL_EXPLORER_DIR) cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
cmd.append("__type_explorer=" + self.remote_type_explorer_dir(type)) cmd.append("__type_explorer=" + self.path.remote_type_explorer_dir(type))
cmd.append("__object=" + self.remote_object_dir(cdist_object)) cmd.append("__object=" + self.path.remote_object_dir(cdist_object))
cmd.append("__object_id=" + self.get_object_id_from_object(cdist_object)) cmd.append("__object_id=" + self.path.get_object_id_from_object(cdist_object))
cmd.append("__object_fq=" + cdist_object) cmd.append("__object_fq=" + cdist_object)
# Need to transfer at least the parameters for objects to be useful # Need to transfer at least the parameters for objects to be useful
self.transfer_object_parameter(cdist_object) self.path.transfer_object_parameter(cdist_object)
explorers = self.list_type_explorers(type) explorers = self.path.list_type_explorers(type)
for explorer in explorers: for explorer in explorers:
remote_cmd = cmd + [os.path.join(self.remote_type_explorer_dir(type), explorer)] remote_cmd = cmd + [os.path.join(self.path.remote_type_explorer_dir(type), explorer)]
output = os.path.join(self.type_explorer_output_dir(cdist_object), explorer) output = os.path.join(self.path.type_explorer_output_dir(cdist_object), explorer)
output_fd = open(output, mode='w') output_fd = open(output, mode='w')
log.debug("%s exploring %s using %s storing to %s", log.debug("%s exploring %s using %s storing to %s",
cdist_object, explorer, remote_cmd, output) cdist_object, explorer, remote_cmd, output)
self.run_or_fail(remote_cmd, stdout=output_fd, remote=True) self.run_or_fail(remote_cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
output_fd.close() output_fd.close()
def init_deploy(self): def init_deploy(self):
"""Ensure the base directories are cleaned up""" """Ensure the base directories are cleaned up"""
log.debug("Creating clean directory structure") log.debug("Creating clean directory structure")
self.path.remove_remote_dir(REMOTE_BASE_DIR) self.path.remove_remote_dir(cdist.path.REMOTE_BASE_DIR)
self.path.remote_mkdir(REMOTE_BASE_DIR) self.path.remote_mkdir(cdist.path.REMOTE_BASE_DIR)
def run_initial_manifest(self): def run_initial_manifest(self):
"""Run the initial manifest""" """Run the initial manifest"""
env = { "__manifest" : self.manifest_dir } env = { "__manifest" : self.path.manifest_dir }
self.run_manifest(self.initial_manifest, extra_env=env) self.run_manifest(self.path.initial_manifest, extra_env=env)
def run_type_manifest(self, cdist_object): def run_type_manifest(self, cdist_object):
"""Run manifest for a specific object""" """Run manifest for a specific object"""
type = self.get_type_from_object(cdist_object) type = self.path.get_type_from_object(cdist_object)
manifest = self.type_dir(type, "manifest") manifest = self.path.type_dir(type, "manifest")
log.debug("%s: Running %s", cdist_object, manifest) log.debug("%s: Running %s", cdist_object, manifest)
if os.path.exists(manifest): if os.path.exists(manifest):
env = { "__object" : self.object_dir(cdist_object), env = { "__object" : self.path.object_dir(cdist_object),
"__object_id": self.get_object_id_from_object(cdist_object), "__object_id": self.path.get_object_id_from_object(cdist_object),
"__object_fq": cdist_object, "__object_fq": cdist_object,
"__type": self.type_dir(type) "__type": self.path.type_dir(type)
} }
self.run_manifest(manifest, extra_env=env) self.run_manifest(manifest, extra_env=env)
@ -166,32 +133,32 @@ class Cdist:
"""Run a manifest""" """Run a manifest"""
log.debug("Running manifest %s, env=%s", manifest, extra_env) log.debug("Running manifest %s, env=%s", manifest, extra_env)
env = os.environ.copy() env = os.environ.copy()
env['PATH'] = self.bin_dir + ":" + env['PATH'] env['PATH'] = self.path.bin_dir + ":" + env['PATH']
# Information required in every manifest # Information required in every manifest
env['__target_host'] = self.target_host env['__target_host'] = self.target_host
env['__global'] = self.out_dir env['__global'] = self.path.out_dir
# Legacy stuff to make cdist-type-emulator work # Legacy stuff to make cdist-type-emulator work
env['__cdist_core_dir'] = os.path.join(self.base_dir, "core") env['__cdist_core_dir'] = os.path.join(self.path.base_dir, "core")
env['__cdist_local_base_dir'] = self.temp_dir env['__cdist_local_base_dir'] = self.path.temp_dir
# Submit information to new type emulator # Submit information to new type emulator
env['__cdist_manifest'] = manifest env['__cdist_manifest'] = manifest
env['__cdist_type_base_dir'] = self.type_base_dir env['__cdist_type_base_dir'] = self.path.type_base_dir
# Other environment stuff # Other environment stuff
if extra_env: if extra_env:
env.update(extra_env) env.update(extra_env)
self.shell_run_or_debug_fail(manifest, [manifest], env=env) cdist.exec.shell_run_or_debug_fail(manifest, [manifest], env=env)
def object_run(self, cdist_object, mode): def object_run(self, cdist_object, mode):
"""Run gencode or code for an object""" """Run gencode or code for an object"""
log.debug("Running %s from %s", mode, cdist_object) log.debug("Running %s from %s", mode, cdist_object)
file=os.path.join(self.object_dir(cdist_object), "require") file=os.path.join(self.path.object_dir(cdist_object), "require")
requirements = file_to_list(file) requirements = cdist.path.file_to_list(file)
type = self.get_type_from_object(cdist_object) type = self.path.get_type_from_object(cdist_object)
for requirement in requirements: for requirement in requirements:
log.debug("Object %s requires %s", cdist_object, requirement) log.debug("Object %s requires %s", cdist_object, requirement)
@ -201,22 +168,22 @@ class Cdist:
# Setup env Variable: # Setup env Variable:
# #
env = os.environ.copy() env = os.environ.copy()
env['__target_host'] = self.target_host env['__target_host'] = self.target_host
env['__global'] = self.out_dir env['__global'] = self.path.out_dir
env["__object"] = self.object_dir(cdist_object) env["__object"] = self.path.object_dir(cdist_object)
env["__object_id"] = self.get_object_id_from_object(cdist_object) env["__object_id"] = self.path.get_object_id_from_object(cdist_object)
env["__object_fq"] = cdist_object env["__object_fq"] = cdist_object
env["__type"] = self.type_dir(type) env["__type"] = self.path.type_dir(type)
if mode == "gencode": if mode == "gencode":
paths = [ paths = [
self.type_dir(type, "gencode-local"), self.path.type_dir(type, "gencode-local"),
self.type_dir(type, "gencode-remote") self.path.type_dir(type, "gencode-remote")
] ]
for bin in paths: for bin in paths:
if os.path.isfile(bin): if os.path.isfile(bin):
# omit "gen" from gencode and use it for output base # omit "gen" from gencode and use it for output base
outfile=os.path.join(self.object_dir(cdist_object), outfile=os.path.join(self.path.object_dir(cdist_object),
os.path.basename(bin)[3:]) os.path.basename(bin)[3:])
outfile_fd = open(outfile, "w") outfile_fd = open(outfile, "w")
@ -225,7 +192,7 @@ class Cdist:
outfile_fd.write(CODE_HEADER) outfile_fd.write(CODE_HEADER)
outfile_fd.flush() outfile_fd.flush()
self.shell_run_or_debug_fail(bin, [bin], env=env, stdout=outfile_fd) cdist.exec.shell_run_or_debug_fail(bin, [bin], env=env, stdout=outfile_fd)
outfile_fd.close() outfile_fd.close()
status = os.stat(outfile) status = os.stat(outfile)
@ -238,23 +205,24 @@ class Cdist:
os.chmod(outfile, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) os.chmod(outfile, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
# Mark object as changed # Mark object as changed
open(os.path.join(self.object_dir(cdist_object), "changed"), "w").close() open(os.path.join(self.path.object_dir(cdist_object), "changed"), "w").close()
if mode == "code": if mode == "code":
local_dir = self.object_dir(cdist_object) local_dir = self.path.object_dir(cdist_object)
remote_dir = self.remote_object_dir(cdist_object) remote_dir = self.path.remote_object_dir(cdist_object)
bin = os.path.join(local_dir, "code-local") bin = os.path.join(local_dir, "code-local")
if os.path.isfile(bin): if os.path.isfile(bin):
self.run_or_fail([bin], remote=False) cdist.exec.run_or_fail([bin])
local_remote_code = os.path.join(local_dir, "code-remote") local_remote_code = os.path.join(local_dir, "code-remote")
remote_remote_code = os.path.join(remote_dir, "code-remote") remote_remote_code = os.path.join(remote_dir, "code-remote")
if os.path.isfile(local_remote_code): if os.path.isfile(local_remote_code):
self.transfer_file(local_remote_code, remote_remote_code) self.path.transfer_file(local_remote_code, remote_remote_code)
self.run_or_fail([remote_remote_code], remote=True) # FIXME: remote_prefix
cdist.exec.run_or_fail([remote_remote_code], remote_prefix=self.remote_prefix)
def stage_prepare(self): def stage_prepare(self):
"""Do everything for a deploy, minus the actual code stage""" """Do everything for a deploy, minus the actual code stage"""
@ -278,13 +246,13 @@ class Cdist:
self.run_type_manifest(cdist_object) self.run_type_manifest(cdist_object)
self.objects_prepared.append(cdist_object) self.objects_prepared.append(cdist_object)
objects = self.list_objects() objects = self.path.list_objects()
def stage_run(self): def stage_run(self):
"""The final (and real) step of deployment""" """The final (and real) step of deployment"""
log.debug("Actual run objects") log.debug("Actual run objects")
# Now do the final steps over the existing objects # Now do the final steps over the existing objects
for cdist_object in self.list_objects(): for cdist_object in self.path.list_objects():
log.debug("Run object: %s", cdist_object) log.debug("Run object: %s", cdist_object)
self.object_run(cdist_object, mode="gencode") self.object_run(cdist_object, mode="gencode")
self.object_run(cdist_object, mode="code") self.object_run(cdist_object, mode="code")
@ -308,11 +276,6 @@ class Cdist:
self.deploy_to() self.deploy_to()
self.cleanup() self.cleanup()
def banner(args):
"""Guess what :-)"""
print(BANNER)
sys.exit(0)
def config(args): def config(args):
"""Configure remote system""" """Configure remote system"""
process = {} process = {}
@ -343,11 +306,11 @@ def install(args):
def emulator(): def emulator():
"""Emulate type commands (i.e. __file and co)""" """Emulate type commands (i.e. __file and co)"""
type = os.path.basename(sys.argv[0]) type = os.path.basename(sys.argv[0])
type_dir = os.path.join(os.environ['__cdist_type_base_dir'], type) type_dir = os.path.join(os.environ['__cdist_type_base_dir'], type)
param_dir = os.path.join(type_dir, "parameter") param_dir = os.path.join(type_dir, "parameter")
global_dir = os.environ['__global'] global_dir = os.environ['__global']
object_source = os.environ['__cdist_manifest'] object_source = os.environ['__cdist_manifest']
parser = argparse.ArgumentParser(add_help=False) parser = argparse.ArgumentParser(add_help=False)
@ -457,16 +420,16 @@ def commandline():
help='Set log level to debug', action='store_true') help='Set log level to debug', action='store_true')
# Main subcommand parser # Main subcommand parser
parser['main'] = argparse.ArgumentParser(description='cdist ' + VERSION) parser['main'] = argparse.ArgumentParser(description='cdist ' + cdist.VERSION)
parser['main'].add_argument('-V', '--version', parser['main'].add_argument('-V', '--version',
help='Show version', action='version', help='Show version', action='version',
version='%(prog)s ' + VERSION) version='%(prog)s ' + cdist.VERSION)
parser['sub'] = parser['main'].add_subparsers(title="Commands") parser['sub'] = parser['main'].add_subparsers(title="Commands")
# Banner # Banner
parser['banner'] = parser['sub'].add_parser('banner', parser['banner'] = parser['sub'].add_parser('banner',
add_help=False) add_help=False)
parser['banner'].set_defaults(func=banner) parser['banner'].set_defaults(func=cdist.banner.banner)
# Config and install (common stuff) # Config and install (common stuff)
parser['configinstall'] = argparse.ArgumentParser(add_help=False) parser['configinstall'] = argparse.ArgumentParser(add_help=False)
@ -511,19 +474,24 @@ def commandline():
if __name__ == "__main__": if __name__ == "__main__":
try: try:
if re.match(TYPE_PREFIX, os.path.basename(sys.argv[0])): logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
# Import generic cdist options
sys.path.insert(0,
os.path.abspath(os.path.join(os.path.dirname(__file__),
'../lib')))
import cdist
if re.match(cdist.TYPE_PREFIX, os.path.basename(sys.argv[0])):
emulator() emulator()
else: else:
# Add our own library path import cdist.banner
sys.path.insert(0, import cdist.exec
os.path.abspath(os.path.join(os.path.dirname(__file__),
'../lib')))
import cdist.path import cdist.path
commandline() commandline()
except KeyboardInterrupt: except KeyboardInterrupt:
sys.exit(0) sys.exit(0)
except CdistError as e: except cdist.Error as e:
log.error(e) log.error(e)
sys.exit(1) sys.exit(1)

View file

@ -1 +0,0 @@
cdist

View file

@ -19,6 +19,9 @@
# #
# #
TYPE_PREFIX = "__"
VERSION = "2.0.2"
class Error(Exception): class Error(Exception):
"""Base exception class for this project""" """Base exception class for this project"""
pass pass

46
lib/cdist/banner.py Normal file
View file

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
#
# 2011 Nico Schottelius (nico-cdist at schottelius.org)
#
# 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 logging
import sys
log = logging.getLogger(__name__)
BANNER = """
.. . .x+=:. s
dF @88> z` ^% :8
'88bu. %8P . <k .88
. '*88888bu . .@8Ned8" :888ooo
.udR88N ^"*8888N .@88u .@^%8888" -*8888888
<888'888k beWE "888L ''888E` x88: `)8b. 8888
9888 'Y" 888E 888E 888E 8888N=*8888 8888
9888 888E 888E 888E %8" R88 8888
9888 888E 888F 888E @8Wou 9% .8888Lu=
?8888u../ .888N..888 888& .888888P` ^%888*
"8888P' `"888*"" R888" ` ^"F 'Y"
"P' "" ""
"""
def banner(args):
"""Guess what :-)"""
print(BANNER)
sys.exit(0)

View file

@ -33,7 +33,6 @@ REMOTE_GLOBAL_EXPLORER_DIR = os.path.join(REMOTE_CONF_DIR, "explorer")
CODE_HEADER = "#!/bin/sh -e\n" CODE_HEADER = "#!/bin/sh -e\n"
DOT_CDIST = ".cdist" DOT_CDIST = ".cdist"
TYPE_PREFIX = "__"
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -58,7 +57,7 @@ class Path:
def __init__(self, target_host, def __init__(self, target_host,
initial_manifest=False, remote_user="root", initial_manifest=False, remote_user="root",
base_dir=None, debug=False): remote_prefix=False, base_dir=None, debug=False):
# Base and Temp Base # Base and Temp Base
if base_dir: if base_dir:
@ -70,7 +69,10 @@ class Path:
self.target_host = target_host self.target_host = target_host
self.remote_user = remote_user self.remote_user = remote_user
self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host] if remote_prefix:
self.remote_prefix = remote_prefix
else:
self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
self.conf_dir = os.path.join(self.base_dir, "conf") self.conf_dir = os.path.join(self.base_dir, "conf")
self.cache_base_dir = os.path.join(self.base_dir, "cache") self.cache_base_dir = os.path.join(self.base_dir, "cache")