From 6e58034ebb5d94d90bd51ac0b5380da16e5b31cd Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Tue, 27 Nov 2012 23:13:12 -0800 Subject: [PATCH 1/9] Use requirement checks and not anvil version Instead of using the anvil version in the bootstrap identifer file use the checksum of the pip and pkg requirement files instead which is more accurate then the anvil version. Since pkg/pip dependencies for anvil sometimes change inside a version this checksum approach is more resilent to those types of changes as well as being resilent between versions when the dependency list doesn't change. --- smithy | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/smithy b/smithy index ffcec598..6dcb0356 100755 --- a/smithy +++ b/smithy @@ -28,7 +28,6 @@ if [ -n "$SUDO_USER" ]; then fi ARGS="$@" -VER=$(python -c "from anvil import version; print version.version_string()") PWD=`pwd` if [ -z "$BOOT_FILES" ]; then BOOT_FN=".anvil_bootstrapped" @@ -85,10 +84,11 @@ bootstrap_epel() has_bootstrapped() { + checksums=$(get_checksums) for i in $BOOT_FILES; do if [ -f $i ]; then contents=`cat $i` - if [ "$contents" == "$VER" ]; then + if [ "$contents" == "$checksums" ]; then return 0 fi fi @@ -96,6 +96,14 @@ has_bootstrapped() return 1 } +get_checksums() +{ + pkg_checksum=$(md5sum tools/pkg-requires) + pip_checksum=$(md5sum tools/pip-requires) + echo "$pkg_checksum" + echo "$pip_checksum" +} + bootstrap_rhel() { echo "Bootstrapping RHEL: $1" @@ -122,7 +130,7 @@ run_smithy() puke() { # TODO(harlowja) better way to do this?? - cleaned_force=$(python -c "f='$FORCE';print(f.lower().strip())") + cleaned_force=$(python -c "f='$FORCE'; print(f.lower().strip())") if [[ "$cleaned_force" == "yes" ]]; then run_smithy else @@ -146,8 +154,12 @@ if [[ "$TYPE" =~ "Red Hat Enterprise Linux Server" ]]; then fi bootstrap_rhel $RH_VER if [ $? -eq 0 ]; then + # Write the checksums of the requirement files + # which if new requirements are added will cause new checksums + # and a new dependency install... + checksums=$(get_checksums) for i in $BOOT_FILES; do - echo "$VER" > $i + echo -e "$checksums" > $i done run_smithy else From 97f1d69fc89847b3debc13806120d904527603fa Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 28 Nov 2012 19:16:49 -0800 Subject: [PATCH 2/9] Yaml interpolation cleanups + addons Move the if statements for the 'auto' key into a dictionary of keys => functors which will be looked up whenever a yaml 'auto' special value is encountered. This allows others to extend this if desired without having to add new if statements on. Cleanup some type conversions and variable naming also. --- anvil/cfg.py | 58 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/anvil/cfg.py b/anvil/cfg.py index 2b91739f..eda6405e 100644 --- a/anvil/cfg.py +++ b/anvil/cfg.py @@ -139,6 +139,12 @@ class YamlInterpolator(object): self.included = {} self.interpolated = {} self.base = base + self.auto_specials = { + 'ip': utils.get_host_ip, + 'user': sh.getuser, + 'group': sh.getgroupname, + 'home': sh.gethomedir, + } def _interpolate_iterable(self, what): if isinstance(what, (set)): @@ -150,6 +156,8 @@ class YamlInterpolator(object): n_what = [] for v in what: n_what.append(self._interpolate(v)) + if isinstance(what, (tuple)): + n_what = tuple(n_what) return n_what def _interpolate_dictionary(self, what): @@ -174,6 +182,8 @@ class YamlInterpolator(object): n_what = [] for v in what: n_what.append(self._do_include(v)) + if isinstance(what, (tuple)): + n_what = tuple(n_what) return n_what def _interpolate(self, value): @@ -188,13 +198,16 @@ class YamlInterpolator(object): def _interpolate_string(self, what): if not re.search(INTERP_PAT, what): + # Leave it alone if the sub won't do + # anything to begin with return what def replacer(match): who = match.group(1).strip() key = match.group(2).strip() - if self._process_special(who, key): - return self._process_special(who, key) + (is_special, special_value) = self._process_special(who, key) + if is_special: + return special_value if who not in self.interpolated: self.interpolated[who] = self.included[who] self.interpolated[who] = self._interpolate(self.included[who]) @@ -203,37 +216,42 @@ class YamlInterpolator(object): return re.sub(INTERP_PAT, replacer, what) def _process_special(self, who, key): - if key == 'ip' and who == 'auto': - return utils.get_host_ip() - if key == 'user' and who == 'auto': - return sh.getuser() - if who == 'auto': - raise KeyError("Unknown auto key type %s" % (key)) - return None + if who and who.lower() in ['auto']: + if key not in self.auto_specials: + raise KeyError("Unknown auto key %r" % (key)) + functor = self.auto_specials[key] + return (True, functor()) + return (False, None) def _include_string(self, what): if not re.search(INTERP_PAT, what): + # Leave it alone if the sub won't do + # anything to begin with return what def replacer(match): who = match.group(1).strip() key = match.group(2).strip() - if self._process_special(who, key): - return self._process_special(who, key) + (is_special, special_value) = self._process_special(who, key) + if is_special: + return special_value + # Process there includes and then + # fetch the value that should have been + # populated self._process_includes(who) return str(self.included[who][key]) return re.sub(INTERP_PAT, replacer, what) - def _do_include(self, v): - n_v = v - if v and isinstance(v, (basestring, str)): - n_v = self._include_string(v) - elif isinstance(v, dict): - n_v = self._include_dictionary(v) - elif isinstance(v, (list, set, tuple)): - n_v = self._include_iterable(v) - return n_v + def _do_include(self, value): + new_value = value + if value and isinstance(value, (basestring, str)): + new_value = self._include_string(value) + elif isinstance(value, (dict)): + new_value = self._include_dictionary(value) + elif isinstance(value, (list, set, tuple)): + new_value = self._include_iterable(value) + return new_value def _process_includes(self, root): if root in self.included: From 048d0a282febb967a6b15c4a41963c03d5ce3784 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 28 Nov 2012 19:50:42 -0800 Subject: [PATCH 3/9] Add on the hostname auto function. --- anvil/cfg.py | 1 + 1 file changed, 1 insertion(+) diff --git a/anvil/cfg.py b/anvil/cfg.py index eda6405e..26d93187 100644 --- a/anvil/cfg.py +++ b/anvil/cfg.py @@ -144,6 +144,7 @@ class YamlInterpolator(object): 'user': sh.getuser, 'group': sh.getgroupname, 'home': sh.gethomedir, + 'hostname': sh.hostname, } def _interpolate_iterable(self, what): From 30873ea8dd1835e07d7efce754ced2ba9f1395b1 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Wed, 28 Nov 2012 19:51:33 -0800 Subject: [PATCH 4/9] Remove execute functionality not used anymore. --- anvil/shell.py | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/anvil/shell.py b/anvil/shell.py index babf060d..fa502a5a 100644 --- a/anvil/shell.py +++ b/anvil/shell.py @@ -42,7 +42,6 @@ SHELL_QUOTE_REPLACERS = { "$": '\$', '`': '\`', } -ROOT_PATH = os.sep # Locally stash these so that they can not be changed # by others after this is first fetched... @@ -76,6 +75,8 @@ def is_dry_run(): # Not stashed locally since the main entrypoint # actually adjusts this value depending on a command # line option... + # + # TODO(harlowja): probably change that to not work that way... return tu.make_bool(env.get_key('ANVIL_DRYRUN')) @@ -85,13 +86,12 @@ def execute(*cmd, **kwargs): check_exit_code = kwargs.pop('check_exit_code', [0]) cwd = kwargs.pop('cwd', None) env_overrides = kwargs.pop('env_overrides', None) - close_stdin = kwargs.pop('close_stdin', False) ignore_exit_code = kwargs.pop('ignore_exit_code', False) - if isinstance(check_exit_code, bool): + if isinstance(check_exit_code, (bool)): ignore_exit_code = not check_exit_code check_exit_code = [0] - elif isinstance(check_exit_code, int): + elif isinstance(check_exit_code, (int)): check_exit_code = [check_exit_code] run_as_root = kwargs.pop('run_as_root', False) @@ -109,22 +109,28 @@ def execute(*cmd, **kwargs): stdin_fh = subprocess.PIPE stdout_fh = subprocess.PIPE stderr_fh = subprocess.PIPE - close_file_descriptors = True - if 'stdout_fh' in kwargs.keys(): - stdout_fh = kwargs.get('stdout_fh') + stdout_fn = kwargs.get('stdout_fn') + stderr_fn = kwargs.get('stderr_fn') + trace_writer = kwargs.get('tracewriter') - if 'stdin_fh' in kwargs.keys(): - stdin_fh = kwargs.get('stdin_fh') - process_input = None + if 'stdout_fh' in kwargs: + stdout_fh = kwargs['stdout_fh'] + if stdout_fn: + LOG.warn("Stdout file handles and stdout file names can not be used simultaneously!") + stdout_fn = None - if 'stderr_fh' in kwargs.keys(): - stderr_fh = kwargs.get('stderr_fh') + if 'stderr_fh' in kwargs: + stderr_fh = kwargs['stderr_fh'] + if stderr_fn: + LOG.warn("Stderr file handles and stderr file names can not be used simultaneously!") + stderr_fn = None if not shell: LOG.debug('Running cmd: %r' % (execute_cmd)) else: LOG.debug('Running shell cmd: %r' % (execute_cmd)) + if process_input is not None: LOG.debug('With stdin: %s' % (process_input)) if cwd: @@ -145,8 +151,12 @@ def execute(*cmd, **kwargs): return doit if not run_as_root: + # Ensure we drop down to the suid user before the command + # is executed (ensuring we don't run in root mode when we + # should not be) (user_uid, user_gid) = get_suids() - demoter = demoter_functor(user_uid=user_uid, user_gid=user_gid) + if user_uid is not None and user_gid is not None: + demoter = demoter_functor(user_uid=user_uid, user_gid=user_gid) rc = None result = None @@ -157,7 +167,7 @@ def execute(*cmd, **kwargs): else: try: obj = subprocess.Popen(execute_cmd, stdin=stdin_fh, stdout=stdout_fh, stderr=stderr_fh, - close_fds=close_file_descriptors, cwd=cwd, shell=shell, + close_fds=True, cwd=cwd, shell=shell, preexec_fn=demoter, env=process_env) if process_input is not None: result = obj.communicate(str(process_input)) @@ -166,8 +176,6 @@ def execute(*cmd, **kwargs): except OSError as e: raise excp.ProcessExecutionError(description="%s: [%s, %s]" % (e, e.errno, e.strerror), cmd=str_cmd) - if (stdin_fh != subprocess.PIPE and obj.stdin and close_stdin): - obj.stdin.close() rc = obj.returncode if not result: @@ -188,13 +196,10 @@ def execute(*cmd, **kwargs): LOG.debug("A failure may of just happened when running command %r [%s] (%s, %s)", str_cmd, rc, stdout, stderr) # See if a requested storage place was given for stderr/stdout - trace_writer = kwargs.get('tracewriter') - stdout_fn = kwargs.get('stdout_fn') if stdout_fn: write_file(stdout_fn, stdout) if trace_writer: trace_writer.file_touched(stdout_fn) - stderr_fn = kwargs.get('stderr_fn') if stderr_fn: write_file(stderr_fn, stderr) if trace_writer: @@ -204,7 +209,7 @@ def execute(*cmd, **kwargs): def abspth(path): if not path: - path = ROOT_PATH + path = "/" if path == "~": path = gethomedir() return os.path.abspath(path) From 4a74c4585b8ac75eb02a8d12f06a426e5d358697 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Thu, 29 Nov 2012 10:33:50 -0800 Subject: [PATCH 5/9] Only set the dry run value once and don't use an env variable for it --- anvil/__main__.py | 2 +- anvil/shell.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/anvil/__main__.py b/anvil/__main__.py index f76ba24a..fb1435fe 100644 --- a/anvil/__main__.py +++ b/anvil/__main__.py @@ -82,7 +82,7 @@ def run(args): # Stash the dryrun value (if any) if 'dryrun' in args: - env.set("ANVIL_DRYRUN", str(args['dryrun'])) + sh.set_dry_run(args['dryrun']) # Ensure the anvil dirs are there if others are about to use it... ensure_anvil_dirs() diff --git a/anvil/shell.py b/anvil/shell.py index fa502a5a..572dee62 100644 --- a/anvil/shell.py +++ b/anvil/shell.py @@ -48,6 +48,9 @@ SHELL_QUOTE_REPLACERS = { SUDO_UID = env.get_key('SUDO_UID') SUDO_GID = env.get_key('SUDO_GID') +# Set only once +IS_DRYRUN = None + class Process(psutil.Process): def __str__(self): @@ -71,13 +74,17 @@ class Rooted(object): self.engaged = False +def set_dry_run(on_off): + global IS_DRYRUN + if not isinstance(on_off, (bool)): + raise TypeError("Dry run value must be a boolean") + if IS_DRYRUN is not None: + raise RuntimeError("Dry run value has already been previously set to '%s'" % (IS_DRYRUN)) + IS_DRYRUN = on_off + + def is_dry_run(): - # Not stashed locally since the main entrypoint - # actually adjusts this value depending on a command - # line option... - # - # TODO(harlowja): probably change that to not work that way... - return tu.make_bool(env.get_key('ANVIL_DRYRUN')) + return bool(IS_DRYRUN) # Originally borrowed from nova computes execute... From 2088135a5bcf8fbe5104fc37a95f71ec17275881 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Fri, 30 Nov 2012 14:23:43 -0800 Subject: [PATCH 6/9] Add in the ability to enable xunit output. Rename the nova verbose -> log_verbose so it doesn't conflict/overwrite the value that comes in on the command line. --- anvil/components/__init__.py | 6 +++++- anvil/components/helpers/nova.py | 2 +- conf/components/nova.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/anvil/components/__init__.py b/anvil/components/__init__.py index 344255d9..8f3f9cd1 100644 --- a/anvil/components/__init__.py +++ b/anvil/components/__init__.py @@ -856,6 +856,10 @@ class PythonTestingComponent(component.Component): cmd.append('--nologcapture') for e in self._get_test_exclusions(): cmd.append('--exclude=%s' % (e)) + xunit_fn = self.get_option("xunit_filename"): + if xunit_fn: + cmd.append("--with-xunit") + cmd.append("--xunit-file=%s" % (xunit_fn)) return cmd def _use_pep8(self): @@ -922,7 +926,7 @@ class PythonTestingComponent(component.Component): cmd = self._get_test_command() env = self._get_env() with open(os.devnull, 'wb') as null_fh: - if self.get_bool_option("tests_verbose", default_value=False): + if self.get_bool_option("verbose", default_value=False): null_fh = None sh.execute(*cmd, stdout_fh=None, stderr_fh=null_fh, cwd=app_dir, env_overrides=env) diff --git a/anvil/components/helpers/nova.py b/anvil/components/helpers/nova.py index fa40ebf3..800649f2 100644 --- a/anvil/components/helpers/nova.py +++ b/anvil/components/helpers/nova.py @@ -286,7 +286,7 @@ class ConfConfigurator(object): # Used more than once so we calculate it ahead of time hostip = self.installer.get_option('ip') - nova_conf.add('verbose', self.installer.get_bool_option('verbose')) + nova_conf.add('verbose', self.installer.get_bool_option('log_verbose')) # Allow destination machine to match source for resize. nova_conf.add('allow_resize_to_same_host', True) diff --git a/conf/components/nova.yaml b/conf/components/nova.yaml index 804dd307..ac2f307c 100644 --- a/conf/components/nova.yaml +++ b/conf/components/nova.yaml @@ -102,7 +102,7 @@ nova_version: "1.1" scheduler: nova.scheduler.filter_scheduler.FilterScheduler # Should nova be in verbose mode? -verbose: True +log_verbose: True # Virtualization settings # Drivers known (libvirt, xensever, vmware, baremetal) From 313b7d72e4fe605b177a5ded49f49376cffa02a8 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Fri, 30 Nov 2012 18:07:40 -0800 Subject: [PATCH 7/9] More cleanups Move the fail/success/welcome messages from utils into a set of shared message data files that are randomly selected from as needed. Remove self->self symlinks before doing the symlink operation for those that have configuration being written to the place where it will be symlinking to. --- conf/messages/fails.1.txt | 4 ++++ conf/messages/fails.10.txt | 6 ++++++ conf/messages/fails.11.txt | 8 ++++++++ conf/messages/fails.12.txt | 6 ++++++ conf/messages/fails.13.txt | 6 ++++++ conf/messages/fails.14.txt | 5 +++++ conf/messages/fails.15.txt | 5 +++++ conf/messages/fails.16.txt | 5 +++++ conf/messages/fails.17.txt | 4 ++++ conf/messages/fails.18.txt | 6 ++++++ conf/messages/fails.19.txt | 8 ++++++++ conf/messages/fails.2.txt | 4 ++++ conf/messages/fails.20.txt | 4 ++++ conf/messages/fails.21.txt | 6 ++++++ conf/messages/fails.3.txt | 5 +++++ conf/messages/fails.4.txt | 5 +++++ conf/messages/fails.5.txt | 5 +++++ conf/messages/fails.6.txt | 4 ++++ conf/messages/fails.7.txt | 5 +++++ conf/messages/fails.8.txt | 6 ++++++ conf/messages/fails.9.txt | 7 +++++++ conf/messages/stacks.1.txt | 7 +++++++ conf/messages/stacks.2.txt | 6 ++++++ conf/messages/stacks.3.txt | 5 +++++ conf/messages/stacks.4.txt | 6 ++++++ conf/messages/stacks.5.txt | 6 ++++++ conf/messages/stacks.6.txt | 8 ++++++++ conf/messages/success.1.txt | 10 ++++++++++ conf/messages/success.2.txt | 4 ++++ conf/messages/success.3.txt | 7 +++++++ conf/messages/success.4.txt | 6 ++++++ conf/messages/success.5.txt | 5 +++++ conf/messages/success.6.txt | 4 ++++ conf/messages/welcome.1.txt | 1 + conf/messages/welcome.2.txt | 1 + 35 files changed, 190 insertions(+) create mode 100644 conf/messages/fails.1.txt create mode 100644 conf/messages/fails.10.txt create mode 100644 conf/messages/fails.11.txt create mode 100644 conf/messages/fails.12.txt create mode 100644 conf/messages/fails.13.txt create mode 100644 conf/messages/fails.14.txt create mode 100644 conf/messages/fails.15.txt create mode 100644 conf/messages/fails.16.txt create mode 100644 conf/messages/fails.17.txt create mode 100644 conf/messages/fails.18.txt create mode 100644 conf/messages/fails.19.txt create mode 100644 conf/messages/fails.2.txt create mode 100644 conf/messages/fails.20.txt create mode 100644 conf/messages/fails.21.txt create mode 100644 conf/messages/fails.3.txt create mode 100644 conf/messages/fails.4.txt create mode 100644 conf/messages/fails.5.txt create mode 100644 conf/messages/fails.6.txt create mode 100644 conf/messages/fails.7.txt create mode 100644 conf/messages/fails.8.txt create mode 100644 conf/messages/fails.9.txt create mode 100644 conf/messages/stacks.1.txt create mode 100644 conf/messages/stacks.2.txt create mode 100644 conf/messages/stacks.3.txt create mode 100644 conf/messages/stacks.4.txt create mode 100644 conf/messages/stacks.5.txt create mode 100644 conf/messages/stacks.6.txt create mode 100644 conf/messages/success.1.txt create mode 100644 conf/messages/success.2.txt create mode 100644 conf/messages/success.3.txt create mode 100644 conf/messages/success.4.txt create mode 100644 conf/messages/success.5.txt create mode 100644 conf/messages/success.6.txt create mode 100644 conf/messages/welcome.1.txt create mode 100644 conf/messages/welcome.2.txt diff --git a/conf/messages/fails.1.txt b/conf/messages/fails.1.txt new file mode 100644 index 00000000..509cfde1 --- /dev/null +++ b/conf/messages/fails.1.txt @@ -0,0 +1,4 @@ + + __________ +< Failure! > + ---------- diff --git a/conf/messages/fails.10.txt b/conf/messages/fails.10.txt new file mode 100644 index 00000000..b8047f24 --- /dev/null +++ b/conf/messages/fails.10.txt @@ -0,0 +1,6 @@ + + _____________________ +/ We were in the nick \ +| of time. You were | +\ in great peril. / + --------------------- diff --git a/conf/messages/fails.11.txt b/conf/messages/fails.11.txt new file mode 100644 index 00000000..80016e75 --- /dev/null +++ b/conf/messages/fails.11.txt @@ -0,0 +1,8 @@ + + ___________________ +/ I know a dead \ +| parrot when I see | +| one, and I'm | +| looking at one | +\ right now. / + ------------------- diff --git a/conf/messages/fails.12.txt b/conf/messages/fails.12.txt new file mode 100644 index 00000000..b69cdf77 --- /dev/null +++ b/conf/messages/fails.12.txt @@ -0,0 +1,6 @@ + + _________________ +/ Welcome to the \ +| National Cheese | +\ Emporium / + ----------------- diff --git a/conf/messages/fails.13.txt b/conf/messages/fails.13.txt new file mode 100644 index 00000000..339cd208 --- /dev/null +++ b/conf/messages/fails.13.txt @@ -0,0 +1,6 @@ + + ______________________ +/ What is the airspeed \ +| velocity of an | +\ unladen swallow? / + ---------------------- diff --git a/conf/messages/fails.14.txt b/conf/messages/fails.14.txt new file mode 100644 index 00000000..9b151126 --- /dev/null +++ b/conf/messages/fails.14.txt @@ -0,0 +1,5 @@ + + ______________________ +/ Now stand aside, \ +\ worthy adversary. / + ---------------------- diff --git a/conf/messages/fails.15.txt b/conf/messages/fails.15.txt new file mode 100644 index 00000000..35f65931 --- /dev/null +++ b/conf/messages/fails.15.txt @@ -0,0 +1,5 @@ + + ___________________ +/ Okay, we'll call \ +\ it a draw. / + ------------------- diff --git a/conf/messages/fails.16.txt b/conf/messages/fails.16.txt new file mode 100644 index 00000000..32ff05fd --- /dev/null +++ b/conf/messages/fails.16.txt @@ -0,0 +1,5 @@ + + _______________ +/ She turned me \ +\ into a newt! / + --------------- diff --git a/conf/messages/fails.17.txt b/conf/messages/fails.17.txt new file mode 100644 index 00000000..ef55c829 --- /dev/null +++ b/conf/messages/fails.17.txt @@ -0,0 +1,4 @@ + + ___________________ +< Fetchez la vache! > + ------------------- diff --git a/conf/messages/fails.18.txt b/conf/messages/fails.18.txt new file mode 100644 index 00000000..323ecfe7 --- /dev/null +++ b/conf/messages/fails.18.txt @@ -0,0 +1,6 @@ + + __________________________ +/ We'd better not risk \ +| another frontal assault, | +\ that rabbit's dynamite. / + -------------------------- diff --git a/conf/messages/fails.19.txt b/conf/messages/fails.19.txt new file mode 100644 index 00000000..122e0094 --- /dev/null +++ b/conf/messages/fails.19.txt @@ -0,0 +1,8 @@ + + ______________________ +/ This is supposed to \ +| be a happy occasion. | +| Let's not bicker and | +| argue about who | +\ killed who. / + ---------------------- diff --git a/conf/messages/fails.2.txt b/conf/messages/fails.2.txt new file mode 100644 index 00000000..e85ac3a1 --- /dev/null +++ b/conf/messages/fails.2.txt @@ -0,0 +1,4 @@ + + ___________ +< Run away! > + ----------- diff --git a/conf/messages/fails.20.txt b/conf/messages/fails.20.txt new file mode 100644 index 00000000..de24fa34 --- /dev/null +++ b/conf/messages/fails.20.txt @@ -0,0 +1,4 @@ + + _______________________ +< You have been borked. > + ----------------------- diff --git a/conf/messages/fails.21.txt b/conf/messages/fails.21.txt new file mode 100644 index 00000000..2090a414 --- /dev/null +++ b/conf/messages/fails.21.txt @@ -0,0 +1,6 @@ + + __________________ +/ We used to dream \ +| of living in a | +\ corridor! / + ------------------- diff --git a/conf/messages/fails.3.txt b/conf/messages/fails.3.txt new file mode 100644 index 00000000..0852d572 --- /dev/null +++ b/conf/messages/fails.3.txt @@ -0,0 +1,5 @@ + + ______________________ +/ NOBODY expects the \ +\ Spanish Inquisition! / + ---------------------- diff --git a/conf/messages/fails.4.txt b/conf/messages/fails.4.txt new file mode 100644 index 00000000..3c152600 --- /dev/null +++ b/conf/messages/fails.4.txt @@ -0,0 +1,5 @@ + + ______________________ +/ Spam spam spam spam \ +\ baked beans and spam / + ---------------------- diff --git a/conf/messages/fails.5.txt b/conf/messages/fails.5.txt new file mode 100644 index 00000000..e2b4f0d9 --- /dev/null +++ b/conf/messages/fails.5.txt @@ -0,0 +1,5 @@ + + ____________________ +/ Brave Sir Robin \ +\ ran away. / + -------------------- diff --git a/conf/messages/fails.6.txt b/conf/messages/fails.6.txt new file mode 100644 index 00000000..353f3078 --- /dev/null +++ b/conf/messages/fails.6.txt @@ -0,0 +1,4 @@ + + _______________________ +< Message for you, sir. > + ----------------------- diff --git a/conf/messages/fails.7.txt b/conf/messages/fails.7.txt new file mode 100644 index 00000000..f9dabbde --- /dev/null +++ b/conf/messages/fails.7.txt @@ -0,0 +1,5 @@ + + ____________________ +/ We are the knights \ +\ who say.... NI! / + -------------------- diff --git a/conf/messages/fails.8.txt b/conf/messages/fails.8.txt new file mode 100644 index 00000000..937e617f --- /dev/null +++ b/conf/messages/fails.8.txt @@ -0,0 +1,6 @@ + + ____________________ +/ Now go away or I \ +| shall taunt you a | +\ second time. / + -------------------- diff --git a/conf/messages/fails.9.txt b/conf/messages/fails.9.txt new file mode 100644 index 00000000..c054dffa --- /dev/null +++ b/conf/messages/fails.9.txt @@ -0,0 +1,7 @@ + + ____________________ +/ It's time for the \ +| penguin on top of | +| your television to | +\ explode. / + -------------------- diff --git a/conf/messages/stacks.1.txt b/conf/messages/stacks.1.txt new file mode 100644 index 00000000..ea00c325 --- /dev/null +++ b/conf/messages/stacks.1.txt @@ -0,0 +1,7 @@ + + ___ ____ _____ _ _ ____ _____ _ ____ _ __ + / _ \| _ \| ____| \ | / ___|_ _|/ \ / ___| |/ / +| | | | |_) | _| | \| \___ \ | | / _ \| | | ' / +| |_| | __/| |___| |\ |___) || |/ ___ \ |___| . \ + \___/|_| |_____|_| \_|____/ |_/_/ \_\____|_|\_\ + diff --git a/conf/messages/stacks.2.txt b/conf/messages/stacks.2.txt new file mode 100644 index 00000000..6d38093e --- /dev/null +++ b/conf/messages/stacks.2.txt @@ -0,0 +1,6 @@ + + ___ ___ ___ _ _ ___ _____ _ ___ _ __ + / _ \| _ \ __| \| / __|_ _/_\ / __| |/ / +| (_) | _/ _|| .` \__ \ | |/ _ \ (__| ' < + \___/|_| |___|_|\_|___/ |_/_/ \_\___|_|\_\ + diff --git a/conf/messages/stacks.3.txt b/conf/messages/stacks.3.txt new file mode 100644 index 00000000..478240b3 --- /dev/null +++ b/conf/messages/stacks.3.txt @@ -0,0 +1,5 @@ + +____ ___ ____ _ _ ____ ___ ____ ____ _ _ +| | |__] |___ |\ | [__ | |__| | |_/ +|__| | |___ | \| ___] | | | |___ | \_ + diff --git a/conf/messages/stacks.4.txt b/conf/messages/stacks.4.txt new file mode 100644 index 00000000..0f2ddfb9 --- /dev/null +++ b/conf/messages/stacks.4.txt @@ -0,0 +1,6 @@ + + _ ___ ___ _ _ __ ___ _ __ _ _ + / \| o \ __|| \| |/ _||_ _|/ \ / _|| |// +( o ) _/ _| | \\ |\_ \ | || o ( (_ | ( + \_/|_| |___||_|\_||__/ |_||_n_|\__||_|\\ + diff --git a/conf/messages/stacks.5.txt b/conf/messages/stacks.5.txt new file mode 100644 index 00000000..bca585d2 --- /dev/null +++ b/conf/messages/stacks.5.txt @@ -0,0 +1,6 @@ + + _ ___ ___ _ __ ___ _____ _ __ _ + ,' \ / o |/ _/ / |/ /,' _//_ _/.' \ ,'_/ / //7 +/ o |/ _,'/ _/ / || /_\ `. / / / o // /_ / ,' +|_,'/_/ /___//_/|_//___,' /_/ /_n_/ |__//_/\\ + diff --git a/conf/messages/stacks.6.txt b/conf/messages/stacks.6.txt new file mode 100644 index 00000000..9e0f4b0a --- /dev/null +++ b/conf/messages/stacks.6.txt @@ -0,0 +1,8 @@ + + _____ ___ ___ _ _ ___ _____ _____ ___ _ _ +( _ )( _`\ ( _`\ ( ) ( )( _`\(_ _)( _ )( _`\ ( ) ( ) +| ( ) || |_) )| (_(_)| `\| || (_(_) | | | (_) || ( (_)| |/'/' +| | | || ,__/'| _)_ | , ` |`\__ \ | | | _ || | _ | , < +| (_) || | | (_( )| |`\ |( )_) | | | | | | || (_( )| |\`\ +(_____)(_) (____/'(_) (_)`\____) (_) (_) (_)(____/'(_) (_) + diff --git a/conf/messages/success.1.txt b/conf/messages/success.1.txt new file mode 100644 index 00000000..f73d4c97 --- /dev/null +++ b/conf/messages/success.1.txt @@ -0,0 +1,10 @@ + + ___________ +/ You shine \ +| out like | +| a shaft | +| of gold | +| when all | +| around is | +\ dark. / + ----------- diff --git a/conf/messages/success.2.txt b/conf/messages/success.2.txt new file mode 100644 index 00000000..8c59131a --- /dev/null +++ b/conf/messages/success.2.txt @@ -0,0 +1,4 @@ + + ______________________________ +< I'm a lumberjack and I'm OK. > + ------------------------------ diff --git a/conf/messages/success.3.txt b/conf/messages/success.3.txt new file mode 100644 index 00000000..3b724f78 --- /dev/null +++ b/conf/messages/success.3.txt @@ -0,0 +1,7 @@ + + ____________________ +/ Australia! \ +| Australia! | +| Australia! | +\ We love you, amen. / + -------------------- diff --git a/conf/messages/success.4.txt b/conf/messages/success.4.txt new file mode 100644 index 00000000..b34d774f --- /dev/null +++ b/conf/messages/success.4.txt @@ -0,0 +1,6 @@ + + ______________ +/ Say no more, \ +| Nudge nudge | +\ wink wink. / + -------------- diff --git a/conf/messages/success.5.txt b/conf/messages/success.5.txt new file mode 100644 index 00000000..740ccc0a --- /dev/null +++ b/conf/messages/success.5.txt @@ -0,0 +1,5 @@ + + ________________ +/ And there was \ +\ much rejoicing / + ---------------- diff --git a/conf/messages/success.6.txt b/conf/messages/success.6.txt new file mode 100644 index 00000000..db282288 --- /dev/null +++ b/conf/messages/success.6.txt @@ -0,0 +1,4 @@ + + __________ +< Success! > + ---------- \ No newline at end of file diff --git a/conf/messages/welcome.1.txt b/conf/messages/welcome.1.txt new file mode 100644 index 00000000..31252eb3 --- /dev/null +++ b/conf/messages/welcome.1.txt @@ -0,0 +1 @@ +And now for something completely different! \ No newline at end of file diff --git a/conf/messages/welcome.2.txt b/conf/messages/welcome.2.txt new file mode 100644 index 00000000..09d761c8 --- /dev/null +++ b/conf/messages/welcome.2.txt @@ -0,0 +1 @@ +Let us get on with the show! \ No newline at end of file From 7ffd010d7bec0fcdb7d946df0a7f06c11e2c6c25 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Fri, 30 Nov 2012 18:40:12 -0800 Subject: [PATCH 8/9] Don't forget pip --- tools/pkg-requires | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/pkg-requires b/tools/pkg-requires index 710fa447..77a1e74a 100644 --- a/tools/pkg-requires +++ b/tools/pkg-requires @@ -1,3 +1,4 @@ +PyYAML gcc git pylint @@ -6,6 +7,6 @@ python-cheetah python-iso8601 python-netifaces python-ordereddict +python-pip python-progressbar python-psutil -PyYAML From a171eeb85f3b9707207d44f9564e209d90552ee8 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Sat, 1 Dec 2012 14:20:05 -0800 Subject: [PATCH 9/9] Additional cleanups and comments --- anvil/action.py | 42 ++++++++++++++++++++++++++++++++++++------ anvil/colorizer.py | 12 +++++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/anvil/action.py b/anvil/action.py index d3853566..c1d880c6 100644 --- a/anvil/action.py +++ b/anvil/action.py @@ -33,6 +33,10 @@ from anvil.utils import OrderedDict LOG = logging.getLogger(__name__) +# Include the general yaml during all interpolation +# actions since it typically contains useful shared settings... +BASE_YAML_INTERP = ('general', ) + class PhaseFunctors(object): def __init__(self, start, run, end): @@ -74,7 +78,7 @@ class Action(object): already_gotten = set() for c in component_order: instance = instances[c] - wanted_passwords = instance.get_option('wanted_passwords') or [] + wanted_passwords = instance.get_option('wanted_passwords') if not wanted_passwords: continue for (name, prompt) in wanted_passwords.items(): @@ -160,11 +164,18 @@ class Action(object): sibling_instances[action][name] = a_sibling return there_siblings + def _get_interpolated_names(self, name): + # Return which sources that will be interpolated from + # Note(harlowja): if one of the bases here pulls in + # another yaml, it will be done automatically so this + # list is more of the starting list and not the end list... + return list(BASE_YAML_INTERP) + [name] + def _get_interpolated_options(self, name): - interpolated_opts = {} - for c in ['general', name]: - interpolated_opts.update(self.interpolator.extract(c)) - return interpolated_opts + opts = {} + for c in self._get_interpolated_names(name): + opts.update(self.interpolator.extract(c)) + return opts def _construct_instances(self, persona): """ @@ -240,6 +251,7 @@ class Action(object): utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) def _get_phase_filename(self, phase_name): + # Do some canonicalization of the phase name so its in a semi-standard format... phase_name = phase_name.lower().strip() phase_name = phase_name.replace("-", '_') phase_name = phase_name.replace(" ", "_") @@ -251,12 +263,23 @@ class Action(object): """ Run a given 'functor' across all of the components, in order. """ + # All the results for each component end up in here + # in the order in which they ran... component_results = OrderedDict() + + # This phase recorder will be used to check if a given component + # and action has ran in the past, if so that components action + # will not be ran again. It will also be used to mark that a given + # component has completed a phase (if that phase runs). if not phase_name: phase_recorder = phase.NullPhaseRecorder() else: phase_recorder = phase.PhaseRecorder(self._get_phase_filename(phase_name)) + # These phase recorders will be used to undo other actions activities + # ie, when an install completes you want to uninstall phase to be + # removed from that actions phase file (and so on). This list will be + # used to accomplish that. neg_phase_recs = [] if inv_phase_names: for n in inv_phase_names: @@ -266,7 +289,14 @@ class Action(object): neg_phase_recs.append(phase.PhaseRecorder(self._get_phase_filename(n))) def change_activate(instance, on_off): - # Activate/deactivate them and there siblings (if any) + # Activate/deactivate a component instance and there siblings (if any) + # + # This is used when you say are looking at components + # that have been activated before your component has been. + # + # Typically this is useful for checking if a previous component + # has a shared dependency with your component and if so then there + # is no need to reinstall said dependency... instance.activated = on_off for (_name, sibling_instance) in instance.siblings.items(): sibling_instance.activated = on_off diff --git a/anvil/colorizer.py b/anvil/colorizer.py index a583cb54..e1580d69 100644 --- a/anvil/colorizer.py +++ b/anvil/colorizer.py @@ -23,13 +23,15 @@ from anvil import type_utils as tu COLORS = termcolor.COLORS.keys() +LOG_COLOR = True +if 'LOG_COLOR' in env.get(): + LOG_COLOR = tu.make_bool(env.get_key('LOG_COLOR')) +if not sys.stdout.isatty(): + LOG_COLOR = False + def color_enabled(): - if 'LOG_COLOR' in env.get() and not tu.make_bool(env.get_key('LOG_COLOR')): - return False - if not sys.stdout.isatty(): - return False - return True + return LOG_COLOR def quote(data, quote_color='green', **kargs):