move to archive, cleaning up for golive

This commit is contained in:
2018-01-24 18:30:48 -06:00
parent 5f1be2380c
commit c1f552b269
92 changed files with 600 additions and 0 deletions

257
archive/slack-runtime/bin/distro Executable file
View File

@@ -0,0 +1,257 @@
#!/bin/sh
# Observium License Version 1.0
#
# Copyright (c) 2013 Joe Holden
#
# The intent of this license is to establish the freedom to use, share and contribute to
# the software regulated by this license.
#
# This license applies to any software containing a notice placed by the copyright holder
# saying that it may be distributed under the terms of this license. Such software is herein
# referred to as the Software. This license covers modification and distribution of the
# Software.
#
# Granted Rights
#
# 1. You are granted the non-exclusive rights set forth in this license provided you agree to
# and comply with any and all conditions in this license. Whole or partial distribution of the
# Software, or software items that link with the Software, in any form signifies acceptance of
# this license.
#
# 2. You may copy and distribute the Software in unmodified form provided that the entire package,
# including - but not restricted to - copyright, trademark notices and disclaimers, as released
# by the initial developer of the Software, is distributed.
#
# 3. You may make modifications to the Software and distribute your modifications, in a form that
# is separate from the Software, such as patches. The following restrictions apply to modifications:
#
# a. Modifications must not alter or remove any copyright notices in the Software.
# b. When modifications to the Software are released under this license, a non-exclusive royalty-free
# right is granted to the initial developer of the Software to distribute your modification in
# future versions of the Software provided such versions remain available under these terms in
# addition to any other license(s) of the initial developer.
#
# Limitations of Liability
#
# In no event shall the initial developers or copyright holders be liable for any damages whatsoever,
# including - but not restricted to - lost revenue or profits or other direct, indirect, special,
# incidental or consequential damages, even if they have been advised of the possibility of such damages,
# except to the extent invariable law, if any, provides otherwise.
#
# No Warranty
#
# The Software and this license document are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# URL: https://github.com/joeholden/distroscript/
# README: https://raw.github.com/joeholden/distroscript/master/README.md
# Shells are made of dicks.
DISTROSCRIPT="1.0.15"
if [ -z ${DISTROFORMAT} ]; then
DISTROFORMAT="pipe"
fi
if [ -n "${AGENT_LIBDIR}" -o -n "${MK_LIBDIR}" ]; then
# Set output for check_mk/observium agent
DISTROFORMAT="export"
fi
getos() {
OS=`uname -s`
if [ "${OS}" = "SunOS" ]; then
OS="Solaris"
elif [ "${OS}" = "DragonFly" ]; then
OS="DragonFlyBSD"
fi
export OS
return 0
}
getkernel() {
KERNEL=`uname -r`
export KERNEL
return 0
}
getdistro() {
if [ "${OS}" = "Linux" ]; then
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO=`echo ${NAME} | awk '{print $1}'`
elif [ -x /usr/bin/lsb_release ]; then
DISTRO=`/usr/bin/lsb_release -si 2>/dev/null`
elif [ -f /etc/redhat-release ]; then
DISTRO=`cat /etc/redhat-release | awk '{print $1}'`
elif [ -f /etc/fedora-release ]; then
DISTRO="Fedora"
elif [ -f /etc/mandriva-release ]; then
DISTRO="Mandriva"
elif [ -f /etc/arch-release ]; then
DISTRO="ArchLinux"
elif [ -f /etc/gentoo-release ]; then
DISTRO="Gentoo"
elif [ -f /etc/SuSE-release ]; then
DISTRO="SuSE"
elif [ -f /etc/mandrake-release ]; then
DISTRO="Mandrake"
elif [ -f /etc/debian_version ]; then
# shit based on debian
if [ -f /etc/mailcleaner/etc/mailcleaner/version.def ]; then
DISTRO="MailCleaner"
else
DISTRO="Debian"
fi
elif [ -f /etc/UnitedLinux-release ]; then
DISTRO="UnitedLinux"
elif [ -f /etc/openwrt_version ]; then
DISTRO="OpenWRT"
elif [ -f /etc/slackware-version ]; then
DISTRO="Slackware"
else
DISTRO="Unknown"
fi
# Fixing some Distro names
if [ "${DISTRO}" = "Debian GNU/Linux" ]; then
DISTRO="Debian"
elif [ "${DISTRO}" = "Red" -o "${DISTRO}" = "RedHatEnterpriseServer" ]; then
DISTRO="RedHat"
elif [ "${DISTRO}" = "Arch" ]; then
DISTRO="ArchLinux"
fi
elif [ "${OS}" = "FreeBSD" ]; then
if [ -f /etc/platform -a -f /etc/version ]; then
DISTRO="pfSense"
elif [ -f /etc/platform -a -f /etc/prd.name ]; then
DISTRO=`cat /etc/prd.name`
elif [ -f /usr/local/bin/pbreg ]; then
DISTRO="PC-BSD"
elif [ -f /tmp/freenas_config.md5 ]; then
DISTRO="FreeNAS"
else
DISTRO=
fi
elif [ "${OS}" = "Solaris" ]; then
DISTRO=`head -n 1 /etc/release | awk '{print $1}'`
if [ "${DISTRO}" = "Solaris" -o "${DISTRO}" = "Oracle" ]; then
DISTRO=
fi
elif [ "${OS}" = "Darwin" ]; then
case `uname -m` in
AppleTV2*)
DISTRO="AppleTV2"
;;
AppleTV3*)
DISTRO="AppleTV3"
;;
iPhone*)
DISTRO="iPhone"
;;
iPod*)
DISTRO="iPOD"
;;
*)
DISTRO="OSX"
;;
esac
else
DISTRO=
fi
export DISTRO
return 0
}
getarch() {
if [ "${OS}" = "Solaris" ]; then
ARCH=`isainfo -k`
elif [ "${OS}" = "Darwin" ]; then
ARCH=`uname -p`
else
ARCH=`uname -m`
fi
if [ "${OS}" = "Linux" ]; then
if [ "${ARCH}" = "x86_64" ]; then
ARCH="amd64"
elif [ "${ARCH}" = "i486" -o "${ARCH}" = "i586" -o "${ARCH}" = "i686" ]; then
ARCH="i386"
fi
fi
export ARCH
return 0
}
getversion() {
if [ "${OS}" = "FreeBSD" -o "${OS}" = "DragonFlyBSD" ]; then
if [ "${DISTRO}" = "pfSense" ]; then
VERSION=`cat /etc/version`
elif [ "${DISTRO}" = "PC-BSD" ]; then
VERSION=`pbreg get /PC-BSD/Version`
elif [ -f /etc/prd.version ]; then
VERSION=`cat /etc/prd.version`
else
VERSION=`uname -i`
fi
elif [ "${OS}" = "OpenBSD" -o "${OS}" = "NetBSD" ]; then
VERSION=`uname -v`
elif [ "${OS}" = "Linux" ]; then
if [ "${DISTRO}" = "OpenWRT" ]; then
VERSION=`cat /etc/openwrt_version`
elif [ "${DISTRO}" = "Slackware" ]; then
VERSION=`cat /etc/slackware-version | cut -d" " -f2`
elif [ -f /etc/redhat-release ]; then
VERSION=`cat /etc/redhat-release | sed 's/.*release\ //' | sed 's/\ .*//'`
elif [ -x /usr/bin/lsb_release ]; then
VERSION=`lsb_release -sr 2>/dev/null`
elif [ -f /etc/os-release ]; then
. /etc/os-release
VERSION=${VERSION_ID}
else
VERSION=
fi
elif [ "${OS}" = "Darwin" ]; then
VERSION=`sw_vers -productVersion`
elif [ "${OS}" = "Solaris" ]; then
VERSION=`uname -v`
fi
export VERSION
return 0
}
if [ -z ${DISTROEXEC} ]; then
getos
getkernel
getarch
getdistro
getversion
if [ "${AGENT_LIBDIR}" -o "${MK_LIBDIR}" ]; then
echo "<<<distro>>>"
fi
if [ "${DISTROFORMAT}" = "pipe" ]; then
echo "${OS}|${KERNEL}|${ARCH}|${DISTRO}|${VERSION}"
elif [ "${DISTROFORMAT}" = "twopipe" ]; then
echo "${OS}||${KERNEL}||${ARCH}||${DISTRO}||${VERSION}"
elif [ "${DISTROFORMAT}" = "ini" ]; then
echo "[distroscript]"
echo " OS = ${OS}"
echo " KERNEL = ${KERNEL}"
echo " ARCH = ${ARCH}"
echo " DISTRO = ${DISTRO}"
echo " DISTROVER = ${VERSION}"
echo " SCRIPTVER = ${DISTROSCRIPT}"
elif [ "${DISTROFORMAT}" = "export" ]; then
echo "OS=${OS}"
echo "KERNEL=${KERNEL}"
echo "ARCH=${ARCH}"
echo "DISTRO=${DISTRO}"
echo "DISTROVER=${VERSION}"
echo "SCRIPTVER=${DISTROSCRIPT}"
else
echo "Unsupported output format."
exit 1
fi
exit 0
fi

View File

@@ -0,0 +1,60 @@
#!/bin/bash
#A script to bootstrap slack onto any TURNSYS managed system in any environment.
#Use this as a template for writing TURNSYS shell scripts
slack-install()
{
wget http://toolbox.turnsys.net/sysinfra/slack/bin/distro -O /usr/bin/distro
chmod +x /usr/bin/distro
apt-get -y install make perl rsync
mkdir /tmp/slackDist
wget http://toolbox.turnsys.net/sysinfra/slack/slackDist.tar.gz -O /tmp/slackDist/slackDist.tar.gz
cd /tmp/slackDist
tar xvfz slackDist.tar.gz
make install
cd /tmp
rm -rf slackDist
mkdir /root/.ssh
chmod 700 /root/.ssh
chown -R root:root /root/.ssh
wget http://toolbox.turnsys.net/sysinfra/slack/env/SlackConfig-$SERVER_TYPE.config -O /etc/slack.conf
wget http://toolbox.turnsys.net/sysinfra/slack/env/SlackSSH-$SERVER_TYPE.config -O /root/.ssh/config
chmod 400 /root/.ssh/config
wget http://toolbox.turnsys.net/sysinfra/slack/env/SlackSSH-$SERVER_TYPE.key -O /root/.ssh/SlackSSH-$SERVER_TYPE.key
chmod 400 /root/.ssh/SlackSSH-$SERVER_TYPE.key
}
#######################################################################################################################################################
#main() #For ease of searching
# Script starts here
# This code serves as a generic template for entrypoint code which is able to handle multi distro, multi environment execution.
# !!!!! DO NOT WRAP IN A FUNCTION. THESE ARE GLOBAL VARIABLES !!!!!
#######################################################################################################################################################
#If we have a fleet later, we can use this code to do fleet stuff
#if [ $(hostname -s|egrep -i -c -E 'ts|ts[0-9]|ts[0-9][0-9]|ts[0-9][0-9][0-9]|linux') -eq 1 ]; then
#export server_type=ts
#fi
case $server_type in
ts)
export SERVER_TYPE="ts"
;;
*)
export SERVER_TYPE="prod"
;;
esac
#######################################################################################################################################################
#Kick everything off
#
slack-install

39
archive/slack-runtime/dist/Makefile vendored Executable file
View File

@@ -0,0 +1,39 @@
# Makefile for slack/src
# $Id: Makefile 187 2008-03-03 02:00:18Z alan $
include Makefile.common
BACKENDS = slack-getroles slack-installfiles slack-runscript slack-sync slack-stage slack-rolediff
all:
install: install-bin install-conf install-lib install-man
install-bin: all
$(MKDIR) $(DESTDIR)$(sbindir)
$(INSTALL) slack $(DESTDIR)$(sbindir)
$(MKDIR) $(DESTDIR)$(bindir)
$(INSTALL) slack-diff $(DESTDIR)$(bindir)
$(MKDIR) $(DESTDIR)$(slack_libexecdir)
@set -ex;\
for i in $(BACKENDS); do \
$(INSTALL) $$i $(DESTDIR)$(slack_libexecdir); done
$(INSTALL) -d -m $(PRIVDIRMODE) $(DESTDIR)$(slack_localstatedir)
$(INSTALL) -d -m $(PRIVDIRMODE) $(DESTDIR)$(slack_localcachedir)
install-conf: all
$(MKDIR) $(DESTDIR)$(sysconfdir)
$(INSTALL) -m 0644 slack.conf $(DESTDIR)$(sysconfdir)
install-lib: all
$(MKDIR) $(DESTDIR)$(slack_libdir)
$(INSTALL) -m 0644 Slack.pm $(DESTDIR)$(slack_libdir)
install-man: all
clean:
realclean: clean
distclean: clean
test:

27
archive/slack-runtime/dist/Makefile.common vendored Executable file
View File

@@ -0,0 +1,27 @@
# Common code included in every Makefile
# $Id: Makefile.common 189 2008-04-21 00:52:56Z sundell $
PACKAGE=slack
VERSION=0.15.2
DESTDIR =
prefix = /
exec_prefix = /usr
sysconfdir = ${prefix}/etc
mandir = ${exec_prefix}/share/man
bindir = ${exec_prefix}/bin
sbindir = ${exec_prefix}/sbin
libdir = ${exec_prefix}/lib
libexecdir = ${exec_prefix}/lib
localstatedir = ${prefix}/var
slack_libdir = ${libdir}/slack
slack_libexecdir = ${libexecdir}/slack
slack_localstatedir = ${localstatedir}/lib/slack
slack_localcachedir = ${localstatedir}/cache/slack
INSTALL = install
MKDIR = mkdir -p
PRIVDIRMODE = 0700

371
archive/slack-runtime/dist/Slack.pm vendored Executable file
View File

@@ -0,0 +1,371 @@
# $Id: Slack.pm 189 2008-04-21 00:52:56Z sundell $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2008 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
package Slack;
require 5.006;
use strict;
use Carp qw(cluck confess croak);
use File::Find;
use POSIX qw(WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG);
use base qw(Exporter);
use vars qw($VERSION @EXPORT @EXPORT_OK $DEFAULT_CONFIG_FILE);
$VERSION = '0.15.2';
@EXPORT = qw();
@EXPORT_OK = qw();
$DEFAULT_CONFIG_FILE = '/etc/slack.conf';
my $term;
my @default_options = (
'help|h|?',
'version',
'verbose|v+',
'quiet',
'config|C=s',
'source|s=s',
'rsh|e=s',
'cache|c=s',
'stage|t=s',
'root|r=s',
'dry-run|n',
'backup|b',
'backup-dir=s',
'hostname|H=s',
);
sub default_usage ($) {
my ($synopsis) = @_;
return <<EOF;
Usage: $synopsis
Options:
-h, -?, --help
Print this help message and exit.
--version
Print the version number and exit.
-v, --verbose
Be verbose.
--quiet
Don't be verbose (Overrides previous uses of --verbose)
-C, --config FILE
Use this config file instead of '$DEFAULT_CONFIG_FILE'.
-s, --source DIR
Source for slack files
-e, --rsh COMMAND
Remote shell for rsync
-c, --cache DIR
Local cache directory for slack files
-t, --stage DIR
Local staging directory for slack files
-r, --root DIR
Root destination for slack files
-n, --dry-run
Don't write any files to disk -- just report what would have been done.
-b, --backup
Make backups of existing files in ROOT that are overwritten.
--backup-dir DIR
Put backups into this directory.
-H, --hostname HOST
Pretend to be running on HOST, instead of the name given by
gethostname(2).
EOF
}
# Read options from a config file. Arguments:
# file => config file to read
# opthash => hashref in which to store the options
# verbose => whether to be verbose
sub read_config (%) {
my %arg = @_;
my ($config_fh);
local $_;
confess "Slack::read_config: no config file given"
if not defined $arg{file};
$arg{opthash} = {}
if not defined $arg{opthash};
open($config_fh, '<', $arg{file})
or confess "Could not open config file '$arg{file}': $!";
# Make this into a hash so we can quickly see if we're looking
# for a particular option
my %looking_for;
if (ref $arg{options} eq 'ARRAY') {
%looking_for = map { $_ => 1 } @{$arg{options}};
}
while(<$config_fh>) {
chomp;
s/#.*//; # delete comments
s/\s+$//; # delete trailing spaces
next if m/^$/; # skip empty lines
if (m/^[A-Z_]+=\S+/) {
my ($key, $value) = split(/=/, $_, 2);
$key =~ tr/A-Z_/a-z-/;
# Only set options we're looking for
next if (%looking_for and not $looking_for{$key});
# Don't set options that are already set
next if defined $arg{opthash}->{$key};
$arg{verbose} and print STDERR "Slack::read_config: Setting '$key' to '$value'\n";
$arg{opthash}->{$key} = $value;
} else {
cluck "Slack::read_config: Garbage line '$_' in '$arg{file}' line $. ignored";
}
}
close($config_fh)
or confess "Slack::read_config: Could not close config file: $!";
# The verbose option is treated specially in so many places that
# we need to make sure it's defined.
$arg{opthash}->{verbose} ||= 0;
return $arg{opthash};
}
# Just get the exit code from a command that failed.
# croaks if anything weird happened.
sub get_system_exit (@) {
my @command = @_;
if (WIFEXITED($?)) {
my $exit = WEXITSTATUS($?);
return $exit if $exit;
}
if (WIFSIGNALED($?)) {
my $sig = WTERMSIG($?);
croak "'@command' caught sig $sig";
}
if ($!) {
croak "Syserr on system '@command': $!";
}
croak "Unknown error on '@command'";
}
sub check_system_exit (@) {
my @command = @_;
my $exit = get_system_exit(@command);
# Exit is non-zero if get_system_exit() didn't croak.
croak "'@command' exited $exit";
}
# get options from the command line and the config file
# Arguments
# opthash => hashref in which to store options
# usage => usage statement
# required_options => arrayref of options to require -- an exception
# will be thrown if these options are not defined
# command_line_hash => store options specified on the command line here
sub get_options {
my %arg = @_;
use Getopt::Long;
Getopt::Long::Configure('bundling');
if (not defined $arg{opthash}) {
$arg{opthash} = {};
}
if (not defined $arg{usage}) {
$arg{usage} = default_usage($0);
}
my @extra_options = (); # extra arguments to getoptions
if (defined $arg{command_line_options}) {
@extra_options = @{$arg{command_line_options}};
}
# Make a --quiet function that turns off verbosity
$arg{opthash}->{quiet} = sub { $arg{opthash}->{verbose} = 0; };
unless (GetOptions($arg{opthash},
@default_options,
@extra_options,
)) {
print STDERR $arg{usage};
exit 1;
}
if ($arg{opthash}->{help}) {
print $arg{usage};
exit 0;
}
if ($arg{opthash}->{version}) {
print "slack version $VERSION\n";
exit 0;
}
# Get rid of the quiet handler
delete $arg{opthash}->{quiet};
# If we've been given a hashref, save our options there at this
# stage, so the caller can see what was passed on the command line.
# Unfortunately, perl has no .replace function, so we iterate.
if (ref $arg{command_line_hash} eq 'HASH') {
while (my ($k, $v) = each %{$arg{opthash}}) {
$arg{command_line_hash}->{$k} = $v;
}
}
# Use the default config file
if (not defined $arg{opthash}->{config}) {
$arg{opthash}->{config} = $DEFAULT_CONFIG_FILE;
}
# We need to decide whether to be verbose about reading the config file
# Currently we just do it if global verbosity > 2
my $verbose_config = 0;
if (defined $arg{opthash}->{verbose}
and $arg{opthash}->{verbose} > 2) {
$verbose_config = 1;
}
# Read options from the config file, passing along the options we've
# gotten so far
read_config(
file => $arg{opthash}->{config},
opthash => $arg{opthash},
verbose => $verbose_config,
);
# The "verbose" option gets compared a lot and needs to be defined
$arg{opthash}->{verbose} ||= 0;
# The "hostname" option is set specially if it's not defined
if (not defined $arg{opthash}->{hostname}) {
use Sys::Hostname;
$arg{opthash}->{hostname} = hostname;
}
# We can require some options to be set
if (ref $arg{required_options} eq 'ARRAY') {
for my $option (@{$arg{required_options}}) {
if (not defined $arg{opthash}->{$option}) {
croak "Required option '$option' not given on command line or specified in config file!\n";
}
}
}
return $arg{opthash};
}
sub prompt ($) {
my ($prompt) = @_;
if (not defined $term) {
require Term::ReadLine;
$term = new Term::ReadLine 'slack'
}
$term->readline($prompt);
}
# Calls the callback on absolute pathnames of files in the source directory,
# and also on names of directories that don't exist in the destination
# directory (i.e. where $source/foo exists but $destination/foo does not).
sub find_files_to_install ($$$) {
my ($source, $destination, $callback) = @_;
return find ({
wanted => sub {
if (-l or not -d _) {
# Copy all files, links, etc
my $file = $File::Find::name;
&$callback($file);
} elsif (-d _) {
# For directories, we only want to copy it if it doesn't
# exist in the destination yet.
my $dir = $File::Find::name;
# We know the root directory will exist (we make it above),
# so skip the base of the source
(my $short_source = $source) =~ s#/$##;
return if $dir eq $short_source;
# Strip the $source from the path,
# so we can build the destination dir from it.
my $subdir = $dir;
($subdir =~ s#^$source##)
or croak "sub failed: $source|$subdir";
if (not -d "$destination/$subdir") {
&$callback($dir);
}
}
}
},
$source,
);
}
# Runs rsync with the necessary redirection to its filehandles
sub wrap_rsync (@) {
my @command = @_;
my ($pid);
if ($pid = fork) {
# Parent
} elsif (defined $pid) {
# Child
open(STDIN, "<", "/dev/null")
or die "Could not redirect STDIN from /dev/null\n";
# This redirection is necessary because rsync sends
# verbose output to STDOUT
open(STDOUT, ">&STDERR")
or die "Could not redirect STDOUT to STDERR\n";
exec(@command);
die "Could not exec '@command': $!\n";
} else {
die "Could not fork: $!\n";
}
my $kid = waitpid($pid, 0);
if ($kid != $pid) {
die "waitpid returned $kid\n";
} elsif ($?) {
Slack::check_system_exit(@command);
}
}
# Runs rsync with the necessary redirection to its filehandles, but also
# returns an FH to stdin and a PID.
sub wrap_rsync_fh (@) {
my @command = @_;
my ($fh, $pid);
if ($pid = open($fh, "|-")) {
# Parent
} elsif (defined $pid) {
# Child
# This redirection is necessary because rsync sends
# verbose output to STDOUT
open(STDOUT, ">&STDERR")
or die "Could not redirect STDOUT to STDERR\n";
exec(@command);
die "Could not exec '@command': $!\n";
} else {
die "Could not fork: $!\n";
}
return($fh, $pid);
}
1;

329
archive/slack-runtime/dist/slack vendored Executable file
View File

@@ -0,0 +1,329 @@
#!/usr/bin/perl -w
# $Id: slack 180 2008-01-19 08:26:19Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2008 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
# This script is in charge of copying files from the (possibly remote)
# master directory to a local cache, using rsync
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use File::Find;
use POSIX; # for strftime
use constant LIBEXEC_DIR => '/usr/lib/slack';
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
sub run_backend(@);
sub run_conditional_backend($@);
(my $PROG = $0) =~ s#.*/##;
# Arguments to pass to each backends (initialized to a hash of empty arrays)
my %backend_flags = ( map { $_ => [] }
qw(getroles sync stage preview preinstall fixfiles installfiles postinstall)
);
my @roles;
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Get out of wherever (possibly NFS-mounted) we were
chdir("/")
or die "Could not chdir /: $!";
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] [<role>...]");
$usage .= <<EOF;
--preview MODE
Do a diff of scripts and files before running them.
MODE can be one of 'simple' or 'prompt'.
--no-files
Don't install any files in ROOT, but tell rsync to print what
it would do.
--no-scripts
Don't run scripts.
--no-sync
Skip the slack-sync step. (useful if you're pushing stuff into
the CACHE outside of slack)
--role-list
Role list for slack-getroles
--libexec-dir DIR
Look for backend scripts in this directory.
--diff PROG
Use this diff program for previews
--sleep TIME
Randomly sleep between 1 and TIME seconds before starting
operations
EOF
# Options
my %opt = ();
# So we can distinguish stuff on the command line from config file stuff
my %command_line_opt = ();
Slack::get_options(
opthash => \%opt,
command_line_options => [
'preview=s',
'role-list=s',
'no-scripts|noscripts',
'no-files|nofiles',
'no-sync|nosync',
'libexec-dir=s',
'diff=s',
'sleep=i',
],
required_options => [ qw(source cache stage root) ],
command_line_hash => \%command_line_opt,
usage => $usage,
);
# Special options
if ($opt{'dry-run'}) {
$opt{'no-scripts'} = 1;
$opt{'no-files'} = 1;
}
if ($opt{'no-scripts'}) {
for my $action (qw(fixfiles preinstall postinstall)) {
push @{$backend_flags{$action}},
'--dry-run';
}
}
if ($opt{'no-files'}) {
push @{$backend_flags{installfiles}},
'--dry-run';
}
# propagate verbosity - 1 to all backends
if (defined $command_line_opt{'verbose'} and
$command_line_opt{'verbose'} > 1) {
for my $action (keys %backend_flags) {
push @{$backend_flags{$action}},
('--verbose') x ($command_line_opt{'verbose'} - 1);
}
}
# propagate these flags to all the backends
for my $option (qw(config root cache stage source hostname rsh)) {
if ($command_line_opt{$option}) {
for my $action (keys %backend_flags) {
push @{$backend_flags{$action}},
"--$option=$command_line_opt{$option}";
}
}
}
# getroles also can take 'role-list'
if ($command_line_opt{'role-list'}) {
push @{$backend_flags{'getroles'}},
"--role-list=$command_line_opt{'role-list'}";
}
# The libexec dir defaults to this if it wasn't specified
# on the command line or in a config file.
if (not defined $opt{'libexec-dir'}) {
$opt{'libexec-dir'} = LIBEXEC_DIR;
}
# Pass diff option along to slack-rolediff
if ($opt{'diff'}) {
push @{$backend_flags{preview}},
"--diff=$opt{'diff'}";
}
# Preview takes an optional argument. If no argument is given,
# it gets "" from getopt.
if (defined $opt{'preview'}) {
if (not grep /^$opt{'preview'}$/, qw(simple prompt)) {
die "Unknown preview mode '$opt{'preview'}'!";
}
}
# The backup option defaults to on if it wasn't specified
# on the command line or in a config file
if (not defined $opt{backup}) {
$opt{backup} = 1;
}
# Figure out a place to put backups
if ($opt{backup} and $opt{'backup-dir'}) {
push @{$backend_flags{installfiles}},
'--backup',
'--backup-dir='.
$opt{'backup-dir'}.
"/".
strftime('%F-%T', localtime(time))
;
}
# }}}
# Random sleep, helpful when called from cron.
if ($opt{sleep}) {
my $secs = int(rand($opt{sleep})) + 1;
$opt{verbose} and print STDERR "$PROG: sleep $secs\n";
sleep($secs);
}
# Get a list of roles to install from slack-getroles {{{
if (not @ARGV) {
my @command = ($opt{'libexec-dir'}.'/slack-getroles',
@{$backend_flags{'getroles'}});
$opt{verbose} and print STDERR "$PROG: getroles\n";
($opt{verbose} > 2) and print STDERR "$PROG: Calling '@command' to get a list of roles for this host.\n";
my ($roles_pid, $roles_fh);
if ($roles_pid = open($roles_fh, "-|")) {
# Parent
} elsif (defined $roles_pid) {
# Child
exec(@command);
die "Could not exec '@command': $!\n";
} else {
die "Could not fork to run '@command': $!\n";
}
@roles = split(/\s+/, join(" ", <$roles_fh>));
unless (close($roles_fh)) {
Slack::check_system_exit(@command);
}
} else {
@roles = @ARGV;
}
# }}}
# Check role name syntax {{{
for my $role (@roles) {
# Roles MUST begin with a letter. All else is reserved.
if ($role !~ m/^[a-zA-Z]/) {
die "Role '$role' does not begin with a letter!";
}
}
# }}}
$opt{verbose} and print STDERR "$PROG: installing roles: @roles\n";
unless ($opt{'no-sync'}) {
# sync all the roles down at once
$opt{verbose} and print STDERR "$PROG: sync @roles\n";
run_backend('slack-sync',
@{$backend_flags{sync}}, @roles);
}
ROLE: for my $role (@roles) {
# stage
$opt{verbose} and print STDERR "$PROG: stage files $role\n";
run_backend('slack-stage',
@{$backend_flags{stage}}, '--subdir=files', $role);
if ($opt{preview}) {
if ($opt{preview} eq 'simple') {
$opt{verbose} and print STDERR "$PROG: preview $role\n";
# Here, we run the backend in no-prompt mode.
run_conditional_backend(0, 'slack-rolediff',
@{$backend_flags{preview}}, $role);
# ...and we skip further action in the ROLE after showing the diff.
next ROLE;
} elsif ($opt{preview} eq 'prompt') {
$opt{verbose} and print STDERR "$PROG: preview scripts $role\n";
# Here, we want to prompt and just do the scripts, since
# we need to run preinstall and fixfiles before doing the files.
run_conditional_backend(1, 'slack-rolediff',
@{$backend_flags{preview}}, '--subdir=scripts', $role);
} else {
# Should get caught in option processing, above
die "Unknown preview mode!\n";
}
}
$opt{verbose} and print STDERR "$PROG: stage scripts $role\n";
run_backend('slack-stage',
@{$backend_flags{stage}}, '--subdir=scripts', $role);
# preinstall
$opt{verbose} and print STDERR "$PROG: preinstall $role\n";
run_backend('slack-runscript',
@{$backend_flags{preinstall}}, 'preinstall', $role);
# fixfiles
$opt{verbose} and print STDERR "$PROG: fixfiles $role\n";
run_backend('slack-runscript',
@{$backend_flags{fixfiles}}, 'fixfiles', $role);
# preview files
if ($opt{preview} and $opt{preview} eq 'prompt') {
$opt{verbose} and print STDERR "$PROG: preview files $role\n";
run_conditional_backend(1, 'slack-rolediff',
@{$backend_flags{preview}}, '--subdir=files', $role);
}
# installfiles
$opt{verbose} and print STDERR "$PROG: install $role\n";
run_backend('slack-installfiles',
@{$backend_flags{installfiles}}, $role);
# postinstall
$opt{verbose} and print STDERR "$PROG: postinstall $role\n";
run_backend('slack-runscript',
@{$backend_flags{postinstall}}, 'postinstall', $role);
}
exit 0;
sub run_backend (@) {
my ($backend, @args) = @_;
# If we weren't given an explicit path, prepend the libexec dir
unless ($backend =~ m#^/#) {
$backend = $opt{'libexec-dir'} . '/' . $backend;
}
# Assemble our command line
my (@command) = ($backend, @args);
($opt{verbose} > 2) and print STDERR "$PROG: Calling '@command'\n";
unless (system(@command) == 0) {
Slack::check_system_exit(@command);
}
}
sub run_conditional_backend ($@) {
my ($prompt, $backend, @args) = @_;
# If we weren't given an explicit path, prepend the libexec dir
unless ($backend =~ m#^/#) {
$backend = $opt{'libexec-dir'} . '/' . $backend;
}
# Assemble our command line
my (@command) = ($backend, @args);
($opt{verbose} > 2) and print STDERR "$PROG: Calling '@command'\n";
unless (system(@command) == 0) {
my $exit = Slack::get_system_exit(@command);
if ($exit == 1) {
# exit 1 means a difference found or something normal that requires
# a prompt before continuing.
if ($prompt) {
exit 1 unless Slack::prompt("Continue? [yN] ") eq 'y';
}
} else {
# any other non-successful exit is a serious error.
die "'@command' exited $exit";
}
}
}

514
archive/slack-runtime/dist/slack-diff vendored Executable file
View File

@@ -0,0 +1,514 @@
#!/usr/bin/perl -w
# $Id: slack-diff 122 2006-09-27 07:34:32Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2006 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script is a wrapper for diff that gives output about special files
# and file modes. (diff can only compare regular files)
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use Errno;
use File::stat;
use File::Basename;
use File::Find;
use Getopt::Long;
use POSIX qw(SIGPIPE strftime);
use Fcntl qw(:mode); # provides things like S_IFMT that POSIX does not
my $VERSION = '0.1';
(my $PROG = $0) =~ s#.*/##;
my @diff; # diff program to use
my $exit = 0; # our exit code
sub compare ($$);
sub recursive_compare ($$);
sub filetype_to_string ($;$);
sub compare_files ($$);
sub diff ($$);
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Autoflush on STDOUT
$|=1;
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
# Default options
my %opt = (
fakediff => 1,
perms => 1,
'new-file' => 1,
diff => 'diff',
);
# Config and option parsing
my $usage = <<EOF;
Usage: $PROG [options] <file1> <file2>
$PROG -r <dir1> <dir2>
Options:
-u, -U NUM, --unified=NUM
Tell diff to use unified output format.
--diff PROG
Use this program for diffing, instead of "$opt{diff}"
--fakediff
Make a fake diff for file modes and other things that are not file
contents. Default is on, can be disabled with --nofakediff.
--perms
Care about owner, group, and permissions when doing fakediff.
Default is on, can be disabled with --noperms.
-r, --recursive
Recursively compare directories.
-N, --new-file
Treat missing files as empty. Default is on, can be disabled with
--nonew-file.
--unidirectional-new-file
Treat only missing files in the first directory as empty.
--from-file
Treat arguments as a list of files from which to read filenames to
compare, two lines at a time.
-0, --null
Use NULLs instead of newlines as the separator in --from-file mode
--devnullhack
You have a version of diff that can't deal with -N when not in
recursive mode, so we need to feed it /dev/null instead of the
missing file. Default is on, can be disabled with --nodevnullhack.
--version
Output version info
--help
Output this help text
Exit codes:
0 Found no differences
1 Found a difference
2 Had a serious error
3 Found a difference and had a serious error
EOF
{
Getopt::Long::Configure ("bundling");
GetOptions(\%opt,
'help|h|?',
'version',
'null|0',
'devnullhack',
'new-file|N',
'u',
'unified|U=i',
'recursive|r',
'from-file',
'unidirectional-new-file',
'fakediff!',
'perms!',
'diff=s',
) or die $usage;
if ($opt{help}) {
print $usage;
exit 0;
}
if ($opt{version}) {
print "$PROG version $VERSION\n";
exit 0;
}
}
if ($opt{diff}) {
# We split on spaces here to be useful -- so that people can give
# their diff options.
@diff = split(/\s+/, $opt{diff});
} else {
die "$PROG: No diff program!\n";
}
if ($opt{'u'}) {
push @diff, '-u';
} elsif ($opt{'unified'}) {
$opt{'u'} = 1; # We use this value later
push @diff, "--unified=$opt{'unified'}";
}
if (not $opt{'devnullhack'}) {
push @diff, '-N';
}
# usually, sigpipe would be someone quitting their pager, so don't sweat it
$SIG{PIPE} = sub { exit $exit };
if ($opt{'from-file'}) {
local $/ = "\0" if $opt{'null'};
while (my $old = <>) {
my $new = <>;
die "Uneven number of lines in --from-file mode!\n"
if not defined $new;
chomp($old);
chomp($new);
$exit |= compare($old, $new);
}
} else {
die $usage unless $#ARGV == 1;
$exit |= compare($ARGV[0], $ARGV[1]);
}
exit $exit;
##
# Subroutines
sub compare ($$) {
my ($old, $new) = @_;
if ($opt{recursive}) {
return recursive_compare($old, $new);
} else {
return compare_files($old, $new);
}
}
# compare two directories. We do this by walking down the *new*
# directory, and comparing everything that's there to the stuff in
# the old directory
sub recursive_compare ($$) {
my ($olddir, $newdir) = @_;
my ($retval, $basere, $wanted);
my (%seen);
$retval = 0;
if (-d $newdir) {
$basere = qr(^$newdir);
$wanted = sub {
my ($newfile) = $_;
my $oldfile = $newfile;
$oldfile =~ s#$basere#$olddir#;
$seen{$oldfile} = 1;
$retval |= compare_files($oldfile, $newfile);
};
eval { find({ wanted => $wanted , no_chdir => 1}, $newdir) };
if ($@) {
warn "$PROG: error during find: $@\n";
$retval |= 2;
}
}
return $retval
if $opt{'unidirectional-new-file'};
# If we're not unidirectional, we want to go through the old directory
# and diff any files we didn't see in the newdir.
if (-d $olddir) {
$basere = qr(^$olddir);
$wanted = sub {
my ($oldfile) = $_;
my $newfile;
return if $seen{$oldfile};
$newfile = $oldfile;
$newfile =~ s#$basere#$newdir#;
$retval |= compare_files($oldfile, $newfile);
};
eval { find({ wanted => $wanted , no_chdir => 1}, $olddir) };
if ($@) {
warn "$PROG: error during find: $@\n";
$retval |= 2;
}
}
return $retval;
}
# filetype_to_string(mode)
# filetype_to_string(mode, plural)
#
# Takes a mode returned from stat(), returns a noune describing the filetype,
# e.g. "directory", "symlink".
# If the "plural" argument is provided and true, returns the plural form of
# the noun, e.g. "directories", "symlinks".
sub filetype_to_string ($;$) {
my ($mode, $plural) = @_;
if (S_ISREG($mode)) {
return "regular file".($plural ? "s" : "");
} elsif (S_ISDIR($mode)) {
return "director".($plural ? "ies" : "y");
} elsif (S_ISLNK($mode)) {
return "symlink".($plural ? "s" : "");
} elsif (S_ISBLK($mode)) {
return "block device".($plural ? "s" : "");
} elsif (S_ISCHR($mode)) {
return "character device".($plural ? "s" : "");
} elsif (S_ISFIFO($mode)) {
return "fifo".($plural ? "s" : "");
} elsif (S_ISSOCK($mode)) {
return "socket".($plural ? "s" : "");
} else {
return "unknown filetype".($plural ? "s" : "");
}
}
# compare_files(oldfile, newfile)
# This is the actual diffing routine. It's quite long because we need to
# deal with all sorts of special cases. It will print to STDOUT a
# description of the differences between the two files. For regular files,
# diff(1) will be run to show the differences.
#
# return codes:
# 1 found a difference
# 2 had an error
# 3 found a difference and had an error
sub compare_files ($$) {
my ($oldname, $newname) = @_;
my ($old, $new); # stat buffers
my $return = 0;
# Get rid of unsightly double slashes
$oldname =~ s#//#/#g;
$newname =~ s#//#/#g;
eval { $old = lstat($oldname); };
if (not defined $old and not $!{ENOENT}) {
warn "$PROG: Could not stat $oldname: $!\n";
return 2;
}
eval { $new = lstat($newname); };
if (not defined $new and not $!{ENOENT}) {
warn "$PROG: Could not stat $newname: $!\n";
return 2;
}
# At this point, $old or $new should only be undefined if the
# file does not exist.
if (defined $old and defined $new) {
if (S_IFMT($old->mode) != S_IFMT($new->mode)) {
if ($opt{fakediff}) {
fakediff('filetype',
$oldname => filetype_to_string($old->mode),
$newname => filetype_to_string($new->mode),
);
} else {
print "File types differ between ".
filetype_to_string($old->mode)." $oldname and ".
filetype_to_string($new->mode)." $newname\n";
}
return 1;
}
if ($old->nlink != $new->nlink) {
# In recursive mode, we don't care about link counts in directories,
# as we'll pick that up with what files do and don't exist.
unless ($opt{recursive} and S_ISDIR($old->mode)) {
if ($opt{fakediff}) {
fakediff('nlink',
$oldname => $old->nlink,
$newname => $new->nlink,
);
} else {
print "Link counts differ between ".
filetype_to_string($old->mode, 1).
" $oldname and $newname\n";
}
$return = 1;
}
}
if ($old->uid != $new->uid and $opt{perms}) {
if ($opt{fakediff}) {
fakediff('uid',
$oldname => $old->uid,
$newname => $new->uid,
);
} else {
print "Owner differs between ".
filetype_to_string($old->mode, 1).
" $oldname and $newname\n";
}
$return = 1;
}
if ($old->gid != $new->gid and $opt{perms}) {
if ($opt{fakediff}) {
fakediff('gid',
$oldname => $old->gid,
$newname => $new->gid,
);
} else {
print "Group differs between ".
filetype_to_string($old->mode, 1).
" $oldname and $newname\n";
}
$return = 1;
}
if (S_IMODE($old->mode) != S_IMODE($new->mode) and $opt{perms}) {
if ($opt{fakediff}) {
fakediff('mode',
$oldname => sprintf('%04o', S_IMODE($old->mode)),
$newname => sprintf('%04o', S_IMODE($new->mode)),
);
} else {
print "Modes differ between ".
filetype_to_string($old->mode, 1).
" $oldname and $newname\n";
}
$return = 1;
}
# We don't want to compare anything more about sockets, fifos, or
# directories, once we've checked the permissions and link counts
if (S_ISSOCK($old->mode) or
S_ISFIFO($old->mode) or
S_ISDIR($old->mode)) {
return $return;
}
# Check device file devs, and that's it for them
if (S_ISCHR($old->mode) or
S_ISBLK($old->mode)) {
if ($old->rdev != $new->rdev) {
if ($opt{fakediff}) {
fakediff('rdev',
$oldname => $old->rdev,
$newname => $new->rdev,
);
} else {
print "Device numbers differ between ".
filetype_to_string($old->mode, 1).
" $oldname and $newname\n";
}
$return = 1;
}
return $return;
}
# Compare the targets of symlinks
if (S_ISLNK($old->mode)) {
my $oldtarget = readlink $oldname
or (warn("$PROG: Could not readlink($oldname): $!\n"),
return $return | 2);
my $newtarget = readlink $newname
or (warn("$PROG: Could not readlink($newname): $!\n"),
return $return | 2);
if ($oldtarget ne $newtarget) {
if ($opt{fakediff}) {
fakediff('target',
$oldname => $oldtarget,
$newname => $newtarget,
);
} else {
print "Symlink targets differ between $oldname and $newname\n";
}
$return = 1;
}
return $return;
}
if (not S_ISREG($old->mode)) {
warn "$PROG: Don't know what to do with file mode $old->mode!\n";
return 2;
}
} elsif (not defined $old and not defined $new) {
print "Neither $oldname nor $newname exists\n";
return $return;
} elsif (not defined $old) {
if (not S_ISREG($new->mode) or not $opt{'new-file'}) {
print "Only in ".dirname($newname).": ".
filetype_to_string($new->mode)." ".basename($newname)."\n";
return 1;
} elsif ($opt{'devnullhack'}) {
$oldname = '/dev/null';
}
} elsif (not defined $new) {
if (not S_ISREG($old->mode) or not $opt{'new-file'}) {
print "Only in ".dirname($oldname).": ".
filetype_to_string($old->mode)." ".basename($oldname)."\n";
return 1;
} elsif ($opt{'devnullhack'}) {
$newname = '/dev/null';
}
}
# They are regular files! We can actually run diff!
return diff($oldname, $newname) | $return;
}
sub diff ($$) {
my ($oldname, $newname) = @_;
my @command = (@diff, $oldname, $newname);
my $status;
# If we're not specifying unified diff, we need to print a header
# to indicate what's being diffed. (I'm not sure if this actually would
# work for patch, but it does tell our user what's going on).
# FIXME: We only need to specify this if the files are different
print "@command\n"
if not $opt{u};
{
# There is a bug in perl with use warnings FATAL => qw(all)
# that will cause the child process from system() to stick
# around if there is a warning generated.
# Shut off warnings -- we'll catch the error below.
no warnings;
$status = system(@command);
}
return 0 if ($status == 0);
if ($? == -1) {
die "$PROG: failed to execute '@command': $!\n";
}
if ($? & 128) {
die "$PROG: '@command' dumped core\n";
}
if (my $sig = $? & 127) {
die "$PROG: '@command' caught sig $sig\n"
unless ($sig == SIGPIPE);
}
if (my $exit = $? >> 8) {
if ($exit == 1) {
return 1;
} else {
die "$PROG: '@command' returned $exit\n";
}
}
return 0;
}
sub fakediff ($$) {
my ($type, $oldname, $oldvalue, $newname, $newvalue) = @_;
return unless $opt{fakediff};
my $time = strftime('%F %T.000000000 %z', localtime(0));
# We add a suffix onto the filenames to show we're not actually looking
# at file contents. There's no good way to indicate this that's compatible
# with patch, and this is simple enough.
$oldname .= '#~~' . $type;
$newname .= '#~~' . $type;
if ($opt{u}) {
# fake up a unified diff
print <<EOF;
--- $oldname\t$time
+++ $newname\t$time
@@ -1 +1 @@
-$oldvalue
+$newvalue
EOF
} else {
print <<EOF;
diff $oldname $newname
1c1
< $oldvalue
---
> $newvalue
EOF
}
}

161
archive/slack-runtime/dist/slack-getroles vendored Executable file
View File

@@ -0,0 +1,161 @@
#!/usr/bin/perl -w
# $Id: slack-getroles 180 2008-01-19 08:26:19Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2008 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
# This script is in charge of copying files from the (possibly remote)
# master directory to a local cache, using rsync
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
my @rsync = ('rsync',
'--links',
'--times',
);
(my $PROG = $0) =~ s#.*/##;
sub sync_list ();
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Get out of wherever (possibly NFS-mounted) we were
chdir("/")
or die "Could not chdir /: $!";
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options]");
$usage .= <<EOF;
--role-list
Role list location (can be relative to SOURCE)
--remote-role-list
Role list is remote and should be copied down with rsync
(implied by certain forms of role list or SOURCE)
EOF
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
command_line_options => [
'role-list=s',
'remote-role-list',
],
required_options => [ qw(role-list hostname) ],
usage => $usage,
);
# Prepare for backups
if ($opt{backup} and $opt{'backup-dir'}) {
# Make sure backup directory exists
unless (-d $opt{'backup-dir'}) {
($opt{verbose} > 0) and print STDERR "Creating backup directory '$opt{'backup-dir'}'\n";
if (not $opt{'dry-run'}) {
eval { mkpath($opt{'backup-dir'}); };
die "Could not mkpath backup dir '$opt{'backup-dir'}': $@\n" if $@;
}
}
push(@rsync, "--backup", "--backup-dir=$opt{'backup-dir'}");
}
# Pass options along to rsync
if ($opt{'dry-run'}) {
push @rsync, '--dry-run';
}
# Pass options along to rsync
if ($opt{'verbose'} > 1) {
push @rsync, '--verbose';
}
# }}}
# See if role-list is actually relative to source, and pre-pend source
# if need be.
unless ($opt{'role-list'} =~ m#^/# or
$opt{'role-list'} =~ m#^\./# or
$opt{'role-list'} =~ m#^[\w@\.-]+:#) {
if (not defined $opt{source}) {
die "Relative path to role-list given, but source not defined!\n\n$usage\n";
}
$opt{'role-list'} = $opt{source} . '/' . $opt{'role-list'};
}
# auto-detect remote role list
if ($opt{'role-list'} =~ m#^[\w@\.-]+:#) {
$opt{'remote-role-list'} = 1;
}
# Copy a remote list locally
if ($opt{'remote-role-list'}) {
# We need a cache directory if the role list is not local
if (not defined $opt{cache}) {
die "Remote path to role-list given, but cache not defined!\n\n$usage\n";
}
# Look at source type, and add options if necessary
if ($opt{'rsh'} or $opt{'role-list'} =~ m/^[\w@\.-]+::/) {
# This is tunnelled rsync, and so needs an extra option
if ($opt{'rsh'}) {
push @rsync, '-e', $opt{'rsh'};
} else {
push @rsync, '-e', 'ssh';
}
}
sync_list();
}
# Read in the roles list
my @roles = ();
my $host_found = 0;
($opt{verbose} > 0) and print STDERR "$PROG: Reading '$opt{'role-list'}'\n";
open(ROLES, "<", $opt{'role-list'})
or die "Could not open '$opt{'role-list'}' for reading: $!\n";
while(<ROLES>) {
s/#.*//; # Strip comments
chomp;
if (s/^$opt{hostname}:\s*//) {
$host_found++;
push @roles, split();
}
}
close(ROLES)
or die "Could not close '$opt{'role-list'}': $!\n";
if (not $host_found) {
die "Host '$opt{hostname}' not found in '$opt{'role-list'}'!\n";
}
print join("\n", @roles), "\n";
exit 0;
sub sync_list () {
my $source = $opt{'role-list'};
my $destination = $opt{cache} . "/_role_list";
unless (-d $opt{cache}) {
eval { mkpath($opt{cache}); };
die "Could not mkpath '$opt{cache}': $@\n" if $@;
}
# All this to run an rsync command
my @command = (@rsync, $source, $destination);
($opt{verbose} > 0) and print STDERR "$PROG: Calling '@command'\n";
Slack::wrap_rsync(@command);
$opt{'role-list'} = $destination;
}

149
archive/slack-runtime/dist/slack-installfiles vendored Executable file
View File

@@ -0,0 +1,149 @@
#!/usr/bin/perl -w
# $Id: slack-installfiles 180 2008-01-19 08:26:19Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2008 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script is in charge of copying files from the local stage to the root
# of the local filesystem
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
my @rsync = ('rsync',
'--relative',
'--times',
'--perms',
'--group',
'--owner',
'--links',
'--devices',
'--sparse',
'--no-implied-dirs', # SO GOOD!
'--files-from=-',
'--from0',
);
(my $PROG = $0) =~ s#.*/##;
sub install_files ($);
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Get out of wherever (possibly NFS-mounted) we were
chdir("/")
or die "Could not chdir /: $!";
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] <role> [<role>...]");
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
usage => $usage,
required_options => [ qw(root stage) ],
);
# }}}
# Arguments are required
die "No roles given!\n\n$usage" unless @ARGV;
unless (-d $opt{root}) {
if (not $opt{'dry-run'}) {
eval {
mkpath($opt{root});
# We have a tight umask, and a root of mode 0700 would be undesirable
# in most cases.
chmod(0755, $opt{root});
};
die "Could not mkpath destination directory '$opt{root}': $@\n" if $@;
}
warn "WARNING[$PROG]: Created destination directory '".$opt{root}."'\n";
}
# Prepare for backups
if ($opt{backup} and $opt{'backup-dir'}) {
# Make sure backup directory exists
unless (-d $opt{'backup-dir'}) {
($opt{verbose} > 0) and print STDERR "$PROG: Creating backup directory '$opt{'backup-dir'}'\n";
if (not $opt{'dry-run'}) {
eval { mkpath($opt{'backup-dir'}); };
die "Could not mkpath backup dir '$opt{'backup-dir'}': $@\n" if $@;
}
}
push(@rsync, "--backup", "--backup-dir=$opt{'backup-dir'}");
}
# Pass options along to rsync
if ($opt{'dry-run'}) {
push @rsync, '--dry-run';
}
if ($opt{'verbose'} > 1) {
push @rsync, '--verbose';
}
# copy over the new files
for my $role (@ARGV) {
install_files($role);
}
exit 0;
# This subroutine takes care of actually installing the files for a role
sub install_files ($) {
my ($role) = @_;
# final / is important for rsync
my $source = $opt{stage} . "/roles/" . $role . "/files/";
my $destination = $opt{root} . "/";
my @command = (@rsync, $source, $destination);
if (not -d $source) {
($opt{verbose} > 0) and
print STDERR "$PROG: No files to install -- '$source' does not exist\n";
return;
}
# Try to give some sensible message here
if ($opt{verbose} > 0) {
if ($opt{'dry-run'}) {
print STDERR "$PROG: Dry-run syncing '$source' to '$destination'\n";
} else {
print STDERR "$PROG: Syncing '$source' to '$destination'\n";
}
}
my ($fh) = Slack::wrap_rsync_fh(@command);
select((select($fh), $|=1)[0]); # Turn on autoflush
my $callback = sub {
my ($file) = @_;
($file =~ s#^$source##)
or die "sub failed: $source|$file";
print $fh "$file\0";
};
# This will print files to be synced to the $fh
Slack::find_files_to_install($source, $destination, $callback);
# Close fh, waitpid, and check return value
unless (close($fh)) {
Slack::check_system_exit(@command);
}
}

146
archive/slack-runtime/dist/slack-rolediff vendored Executable file
View File

@@ -0,0 +1,146 @@
#!/usr/bin/perl -w
# $Id: slack-rolediff 125 2006-09-27 07:50:07Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2006 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script provides a preview of scripts or files about to be installed.
# Basically, it calls diff -- its smarts are in knowing where things are.
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use File::Find;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
my @diff = ('slack-diff',
'-uN',
);
# directories to compare
my %subdir = (
files => 1,
scripts => 1,
);
(my $PROG = $0) =~ s#.*/##;
sub diff ($$;@);
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Get out of wherever (possibly NFS-mounted) we were
chdir("/")
or die "Could not chdir /: $!";
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] <role> [<role>...]");
$usage .= <<EOF;
--subdir DIR
Check this subdir only. Possible values for DIR are 'files' and
'scripts'.
--diff PROG
Use this program to do diffs. [@diff]
EOF
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
command_line_options => [
'subdir=s',
'diff=s',
],
usage => $usage,
required_options => [ qw(cache stage root) ],
);
# Arguments are required
die "No roles given!\n\n$usage" unless @ARGV;
# We only allow certain values for this option
if ($opt{subdir}) {
unless ($opt{subdir} eq 'files' or $opt{subdir} eq 'scripts') {
die "--subdir option must be 'files' or 'scripts'\n\n$usage";
}
# Only do this subdir
%subdir = ( $opt{subdir} => 1 );
}
# Let people override our diff. Split on spaces so they can pass args.
if ($opt{diff}) {
@diff = split(/\s+/, $opt{diff});
}
# }}}
my $exit = 0;
# Do the diffs
for my $full_role (@ARGV) {
# Split the full role (e.g. google.foogle.woogle) into components
my @role = split(/\./, $full_role);
if ($subdir{scripts}) {
# Then we compare the cache vs the stage
my $old = $opt{stage} . "/roles/" . $full_role . "/scripts";
my $new = $opt{cache} . "/roles/" . $role[0] . "/scripts";
# For scripts, we don't care so much about mode and owner (since those are
# inherited in the CACHE from the SOURCE), so --noperms.
$exit |= diff($old, $new, '--noperms');
}
if ($subdir{files}) {
# Then we compare the stage vs the root
my $old = $opt{root};
my $new = $opt{stage} . "/roles/" . $full_role . "/files";
# For files, we don't care about files that exist in $old but not $new
$exit |= diff($old, $new, '--unidirectional-new-file');
}
}
exit $exit;
sub diff ($$;@) {
my ($old, $new, @options) = @_;
my @command = (@diff, @options);
# return if there's nothing to do
return 0 if (not -d $old and not -d $new);
($opt{verbose} > 0) and print STDERR "$PROG: Previewing with '@command'\n";
my $return = 0;
my $callback = sub {
my ($new_file) = @_;
my $old_file = $new_file;
($old_file =~ s#^$new#$old#)
or die "sub failed: $new|$new_file";
if (system(@command, $old_file, $new_file) != 0) {
$return |= Slack::get_system_exit(@command);
}
};
# We have to use this function, rather than recursive mode for slack-diff,
# because otherwise we'll print a bunch of bogus stuff about directories
# that exist in $ROOT and therefore aren't being synced.
Slack::find_files_to_install($new, $old, $callback);
return $return;
}

111
archive/slack-runtime/dist/slack-runscript vendored Executable file
View File

@@ -0,0 +1,111 @@
#!/usr/bin/perl -w
# $Id: slack-runscript 118 2006-09-25 18:35:17Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2006 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script is in charge of running scripts out of the local stage
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use File::Find;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
# Export these options to the environment of the script
my @export_options = qw(root stage hostname verbose);
(my $PROG = $0) =~ s#.*/##;
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
# Get out of wherever (possibly NFS-mounted) we were
chdir('/')
or die "Could not chdir '/': $!";
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] <action> <role> [<role>...]");
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
usage => $usage,
required_options => \@export_options,
);
my $action = shift || die "No script to run!\n\n$usage";
# Arguments are required
die "No roles given!\n\n$usage" unless @ARGV;
# }}}
# Start with a clean environment
%ENV = (
PATH => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
);
# Export certain variables to the environment. These are guaranteed to
# be set because we require them in get_options above.
for my $option (@export_options) {
my $env_var = $option;
$env_var =~ tr/a-z-/A-Z_/;
$ENV{$env_var} = $opt{$option};
}
# We want to decrement the verbose value for the child if it's set.
$ENV{VERBOSE}-- if $ENV{VERBOSE};
# Run the script for each role given, if it exists and is executable
for my $role (@ARGV) {
my $script_to_run = "$opt{stage}/roles/$role/scripts/$action";
unless (-x $script_to_run) {
if (-e _) {
# A helpful warning
warn "WARNING[$PROG]: Skipping '$script_to_run' because it's not executable\n";
} elsif ($opt{verbose} > 0) {
print STDERR "$PROG: Skipping '$script_to_run' because it doesn't exist\n";
}
next;
}
my $dir;
if ($action eq 'fixfiles') {
$dir = "$opt{stage}/roles/$role/files";
} else {
$dir = "$opt{stage}/roles/$role/scripts";
}
my @command = ($script_to_run , $role);
# It's OK to chdir even if we're not going to run the script.
# Might as well see if it works.
chdir($dir)
or die "Could not chdir '$dir': $!\n";
if ($opt{'dry-run'}) {
($opt{verbose} > 0)
and print STDERR "$PROG: Not calling '@command' in '$dir' ".
"because --dry-run specified.\n";
} else {
($opt{verbose} > 0)
and print STDERR "$PROG: Calling '@command' in '$dir'.\n";
unless (system("script /root/slackLog -a -f -c @command") == 0) {
Slack::check_system_exit(@command);
}
}
chdir('/')
or die "Could not chdir '/': $!\n"
}
exit 0;

View File

@@ -0,0 +1,111 @@
#!/usr/bin/perl -w
# $Id: slack-runscript 118 2006-09-25 18:35:17Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2006 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script is in charge of running scripts out of the local stage
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use File::Find;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
# Export these options to the environment of the script
my @export_options = qw(root stage hostname verbose);
(my $PROG = $0) =~ s#.*/##;
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
# Get out of wherever (possibly NFS-mounted) we were
chdir('/')
or die "Could not chdir '/': $!";
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] <action> <role> [<role>...]");
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
usage => $usage,
required_options => \@export_options,
);
my $action = shift || die "No script to run!\n\n$usage";
# Arguments are required
die "No roles given!\n\n$usage" unless @ARGV;
# }}}
# Start with a clean environment
%ENV = (
PATH => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
);
# Export certain variables to the environment. These are guaranteed to
# be set because we require them in get_options above.
for my $option (@export_options) {
my $env_var = $option;
$env_var =~ tr/a-z-/A-Z_/;
$ENV{$env_var} = $opt{$option};
}
# We want to decrement the verbose value for the child if it's set.
$ENV{VERBOSE}-- if $ENV{VERBOSE};
# Run the script for each role given, if it exists and is executable
for my $role (@ARGV) {
my $script_to_run = "$opt{stage}/roles/$role/scripts/$action";
unless (-x $script_to_run) {
if (-e _) {
# A helpful warning
warn "WARNING[$PROG]: Skipping '$script_to_run' because it's not executable\n";
} elsif ($opt{verbose} > 0) {
print STDERR "$PROG: Skipping '$script_to_run' because it doesn't exist\n";
}
next;
}
my $dir;
if ($action eq 'fixfiles') {
$dir = "$opt{stage}/roles/$role/files";
} else {
$dir = "$opt{stage}/roles/$role/scripts";
}
my @command = ($script_to_run, $role);
# It's OK to chdir even if we're not going to run the script.
# Might as well see if it works.
chdir($dir)
or die "Could not chdir '$dir': $!\n";
if ($opt{'dry-run'}) {
($opt{verbose} > 0)
and print STDERR "$PROG: Not calling '@command' in '$dir' ".
"because --dry-run specified.\n";
} else {
($opt{verbose} > 0)
and print STDERR "$PROG: Calling '@command' in '$dir'.\n";
unless (system(@command) == 0) {
Slack::check_system_exit(@command);
}
}
chdir('/')
or die "Could not chdir '/': $!\n"
}
exit 0;

278
archive/slack-runtime/dist/slack-stage vendored Executable file
View File

@@ -0,0 +1,278 @@
#!/usr/bin/perl -w
# $Id: slack-stage 180 2008-01-19 08:26:19Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2008 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script is in charge of copying files from the local cache
# directory to the local stage, building a unified single tree onstage
# from the multiple trees that are the role + subroles in the cache
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use File::Find;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
my @rsync = ('rsync',
'--recursive',
'--times',
'--ignore-times',
'--perms',
'--sparse',
);
(my $PROG = $0) =~ s#.*/##;
sub check_stage ();
sub sync_role ($$@);
sub apply_default_perms_to_role ($$);
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Get out of wherever (possibly NFS-mounted) we were
chdir("/")
or die "Could not chdir /: $!";
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] <role> [<role>...]");
$usage .= <<EOF;
--subdir DIR
Sync this subdir only. Possible values for DIR are 'files' and
'scripts'.
EOF
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
command_line_options => [
'subdir=s',
],
usage => $usage,
required_options => [ qw(cache stage) ],
);
# Arguments are required
die "No roles given!\n\n$usage" unless @ARGV;
# We only allow certain values for this option
if ($opt{subdir}) {
unless ($opt{subdir} eq 'files' or $opt{subdir} eq 'scripts') {
die "--subdir option must be 'files' or 'scripts'\n\n$usage";
}
} else {
$opt{subdir} = '';
}
# Prepare for backups
if ($opt{backup} and $opt{'backup-dir'}) {
# Make sure backup directory exists
unless (-d $opt{'backup-dir'}) {
($opt{verbose} > 0) and print STDERR "Creating backup directory '$opt{'backup-dir'}'\n";
if (not $opt{'dry-run'}) {
eval { mkpath($opt{'backup-dir'}); };
die "Could not mkpath backup dir '$opt{'backup-dir'}': $@\n" if $@;
}
}
push(@rsync, "--backup", "--backup-dir=$opt{'backup-dir'}");
}
# Pass options along to rsync
if ($opt{'dry-run'}) {
push @rsync, '--dry-run';
}
# Pass options along to rsync
if ($opt{'verbose'} > 1) {
push @rsync, '--verbose';
}
# }}}
# copy over the new files
for my $full_role (@ARGV) {
# Split the full role (e.g. google.foogle.woogle) into components
my @role_parts = split(/\./, $full_role);
die "Internal error: Expect at least one role part" if not @role_parts;
# Reassemble parts one at a time onto @role and sync as we go,
# so we do "google", then "google.foogle", then "google.foogle.woogle"
my @role = ();
# Make sure we've got the right perms before we copy stuff down
check_stage();
# For the base role, do both files and scripts.
push @role, shift @role_parts;
for my $subdir(qw(files scripts)) {
if (not $opt{subdir} or $opt{subdir} eq $subdir) {
($opt{verbose} > 1)
and print STDERR "$PROG: Calling sync_role for $full_role, @role\n";
# @role here will have one element, so sync_role will use --delete
sync_role($full_role, $subdir, @role)
}
}
# For all subroles, just do the files.
# (If we wanted script subroles to work like files, we'd get rid of this
# distinction and simplify the code.)
if (not $opt{subdir} or $opt{subdir} eq 'files') {
while (@role_parts) {
push @role, shift @role_parts;
($opt{verbose} > 1)
and print STDERR "$PROG: Calling sync_role for $full_role, @role\n";
sync_role($full_role, 'files', @role);
}
}
for my $subdir (qw(files scripts)) {
apply_default_perms_to_role($full_role, $subdir)
if (not $opt{subdir} or $opt{subdir} eq $subdir);
}
}
exit 0;
# Make sure the stage directory exists and is mode 0700, to protect files
# underneath in transit
sub check_stage () {
my $stage = $opt{stage} . "/roles";
if (not $opt{'dry-run'}) {
if (not -d $stage) {
($opt{verbose} > 0) and print STDERR "$PROG: Creating '$stage'\n";
eval { mkpath($stage); };
die "Could not mkpath cache dir '$stage': $@\n" if $@;
}
($opt{verbose} > 0) and print STDERR "$PROG: Checking perms on '$stage'\n";
if ($> != 0) {
warn "WARNING[$PROG]: Not superuser; unable to chown files\n";
} else {
chown(0, 0, $stage)
or die "Could not chown 0:0 '$stage': $!\n";
}
chmod(0700, $stage)
or die "Could not chmod 0700 '$stage': $!\n";
}
}
# Copy the files for a role from CACHE to STAGE
sub sync_role ($$@) {
my ($full_role, $subdir, @role) = @_;
my @this_rsync = @rsync;
# If we were only given one role part, we're in the base role
my $in_base_role = (scalar @role == 1);
# For the base role, delete any files that don't exist in the cache.
# Not for the subrole (otherwise we'll delete all files not in
# the subrole, which may be most of them!)
if ($in_base_role) {
push @this_rsync, "--delete";
}
# (a) => a/files
# (a,b,c) => a/files.b.c
my $src_path = $role[0].'/'.join(".", $subdir, @role[1 .. $#role]);
# This one's a little simpler:
my $dst_path = $full_role.'/'.$subdir;
# final / is important for rsync
my $source = $opt{cache} . "/roles/" . $src_path . "/";
my $destination = $opt{stage} . "/roles/" . $dst_path . "/";
if (not -d $destination and -d $source) {
($opt{verbose} > 0) and print STDERR "$PROG: Creating '$destination'\n";
if (not $opt{'dry-run'}) {
eval { mkpath($destination); };
die "Could not mkpath stage dir '$destination': $@\n" if $@;
}
}
# We no longer require the source to exist
if (not -d $source) {
# but we need to remove the destination if the source
# doesn't exist and we're in the base role
if ($in_base_role) {
rmtree($destination);
# rmtree() doesn't throw exceptions or give a return value useful
# for detecting failure, so we just check after the fact.
die "Could not rmtree '$destination' when '$source' missing\n"
if -e $destination;
}
# if we continue, rsync will fail because source is missing,
# so we don't.
return;
}
# All this to run an rsync command
my @command = (@this_rsync, $source, $destination);
($opt{verbose} > 0) and print STDERR "$PROG: Syncing $src_path with '@command'\n";
Slack::wrap_rsync(@command);
}
# This just takes the base role, and chowns/chmods everything under it to
# give it some sensible permissions. Basically, the only thing we preserve
# about the original permissions is the executable bit, since that's the
# only thing source code controls systems like CVS, RCS, Perforce seem to
# preserve.
sub apply_default_perms_to_role ($$) {
my ($role, $subdir) = @_;
my $destination = $opt{stage} . "/roles/" . $role;
if ($subdir) {
$destination .= '/' . $subdir;
}
# If the destination doesn't exist, it's probably because the source didn't
return if not -d $destination;
($opt{verbose} > 0) and print STDERR "$PROG: Setting default perms on $destination\n";
if ($> != 0) {
warn "WARNING[$PROG]: Not superuser; won't be able to chown files\n";
}
# Use File::Find to recurse the directory
find({
# The "wanted" subroutine is called for every directory entry
wanted => sub {
return if $opt{'dry-run'};
($opt{verbose} > 2) and print STDERR "$File::Find::name\n";
if (-l) {
# symlinks shouldn't be in here,
# since we dereference when copying
warn "WARNING[$PROG]: Skipping symlink at $File::Find::name: $!\n";
return;
} elsif (-f _) { # results of last stat saved in the "_"
if (-x _) {
chmod 0555, $_
or die "Could not chmod 0555 $File::Find::name: $!";
} else {
chmod 0444, $_
or die "Could not chmod 0444 $File::Find::name: $!";
}
} elsif (-d _) {
chmod 0755, $_
or die "Could not chmod 0755 $File::Find::name: $!";
} else {
warn "WARNING[$PROG]: Unknown file type at $File::Find::name: $!\n";
}
return if $> != 0; # skip chowning if not superuser
chown 0, 0, $_
or die "Could not chown 0:0 $File::Find::name: $!";
},
# end of wanted function
},
# way down here, we have the directory to traverse with File::Find
$destination,
);
}

169
archive/slack-runtime/dist/slack-sync vendored Executable file
View File

@@ -0,0 +1,169 @@
#!/usr/bin/perl -w
# $Id: slack-sync 180 2008-01-19 08:26:19Z alan $
# vim:sw=2
# vim600:fdm=marker
# Copyright (C) 2004-2008 Alan Sundell <alan@sundell.net>
# All Rights Reserved. This program comes with ABSOLUTELY NO WARRANTY.
# See the file COPYING for details.
#
# This script is in charge of copying files from the (possibly remote)
# master directory to a local cache, using rsync
require 5.006;
use warnings FATAL => qw(all);
use strict;
use sigtrap qw(die untrapped normal-signals
stack-trace any error-signals);
use File::Path;
use constant LIB_DIR => '/usr/lib/slack';
use lib LIB_DIR;
use Slack;
my @rsync = ('rsync',
'--cvs-exclude',
'--recursive',
'--links',
'--copy-links',
'--times',
'--perms',
'--sparse',
'--delete',
'--files-from=-',
'--from0',
);
(my $PROG = $0) =~ s#.*/##;
sub check_cache ($);
sub rsync_source ($$@);
########################################
# Environment
# Helpful prefix to die messages
$SIG{__DIE__} = sub { die "FATAL[$PROG]: @_"; };
# Set a reasonable umask
umask 077;
# Get out of wherever (possibly NFS-mounted) we were
chdir("/")
or die "Could not chdir /: $!";
# Autoflush on STDERR
select((select(STDERR), $|=1)[0]);
########################################
# Config and option parsing {{{
my $usage = Slack::default_usage("$PROG [options] <role> [<role>...]");
# Option defaults
my %opt = ();
Slack::get_options(
opthash => \%opt,
usage => $usage,
required_options => [ qw(source cache) ],
);
# Arguments are required
die "No roles given!\n\n$usage" unless @ARGV;
# Prepare for backups
if ($opt{backup} and $opt{'backup-dir'}) {
# Make sure backup directory exists
unless (-d $opt{'backup-dir'}) {
($opt{verbose} > 0) and print STDERR "Creating backup directory '$opt{'backup-dir'}'\n";
if (not $opt{'dry-run'}) {
eval { mkpath($opt{'backup-dir'}); };
die "Could not mkpath backup dir '$opt{'backup-dir'}': $@\n" if $@;
}
}
push(@rsync, "--backup", "--backup-dir=$opt{'backup-dir'}");
}
# Look at source type, and add options if necessary
if ($opt{'rsh'} or $opt{source} =~ m/^[\w@\.-]+::/) {
# This is tunnelled rsync, and so needs an extra option
if ($opt{'rsh'}) {
push @rsync, '-e', $opt{'rsh'};
} else {
push @rsync, '-e', 'ssh';
}
}
# Pass options along to rsync
if ($opt{'dry-run'}) {
push @rsync, '--dry-run';
}
# Pass options along to rsync
if ($opt{'verbose'} > 1) {
push @rsync, '--verbose';
}
# }}}
my @roles = ();
{
# This hash is just to avoid calling rsync twice if two subroles are
# installed. We only care since it's remote, and therefore slow.
my %roles_to_sync = ();
# copy over the new files
for my $full_role (@ARGV) {
# Get the first element of the role name (the base role)
# e.g., from "google.foogle.woogle", get "google"
my $base_role = (split /\./, $full_role, 2)[0];
$roles_to_sync{$base_role} = 1;
}
@roles = keys %roles_to_sync;
}
my $cache = $opt{cache} . "/roles/";
# Make sure we've got the right perms before we copy stuff down
check_cache($cache);
rsync_source(
$opt{source} . '/roles/',
$cache,
@roles,
);
exit 0;
# Make sure the cache directory exists and is mode 0700, to protect files
# underneath in transit
sub check_cache ($) {
my ($cache) = @_;
if (not $opt{'dry-run'}) {
if (not -d $cache) {
($opt{verbose} > 0) and print STDERR "$PROG: Creating '$cache'\n";
eval { mkpath($cache); };
die "Could not mkpath cache dir '$cache': $@\n" if $@;
}
($opt{verbose} > 0) and print STDERR "$PROG: Checking perms on '$cache'\n";
if ($> != 0) {
warn "WARNING[$PROG]: Not superuser; unable to chown files\n";
} else {
chown(0, 0, $cache)
or die "Could not chown 0:0 '$cache': $!\n";
}
chmod(0700, $cache)
or die "Could not chmod 0700 '$cache': $!\n";
}
}
# Pull down roles from an rsync source
sub rsync_source($$@) {
my ($source, $destination, @roles) = @_;
my @command = (@rsync, $source, $destination);
($opt{verbose} > 0)
and print STDERR "$PROG: Syncing cache with '@command'\n";
my ($fh) = Slack::wrap_rsync_fh(@command);
# Shove the roles down its throat
print $fh join("\0", @roles), "\0";
# Close fh, waitpid, and check return value
unless (close($fh)) {
Slack::check_system_exit(@command);
}
}

0
archive/slack-runtime/dist/slack.conf vendored Executable file
View File

View File

@@ -0,0 +1,6 @@
ROLE_LIST=toolbox.turnsys.net:/local/slack-prod/etc/roles.conf
SOURCE=toolbox.turnsys.net:/local/slack-prod/
CACHE=/var/cache/slack
STAGE=/var/lib/slack/stage
ROOT=/
BACKUP_DIR=/var/lib/slack/backups

View File

@@ -0,0 +1,4 @@
Host toolbox.turnsys.net
User slack-prod
IdentityFile /root/.ssh/SlackSSH-prod.key
StrictHostKeyChecking no

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAycZwe0FuYISsFaHvaplNhb9uplG8YeMkffIKXp633MwihACm
oNoKEQHlqSKD1urZfLYjwf1YBKAPt9QRdIguwsQ3hl3xKpsO+gsmaOpF3eJMVWHZ
dS/T7lplIOcXr0tbUeibQ9p+c+MgICfpdAJvUnuD8grDmaTuvasBat4Ow6rXIzsQ
WKzSrP3iQJ0xeq+mqRIlPP5dwl66RF+dlaloVxlvG95i3u512EkNg+sMt1X5KbhH
ecQSicpA8K2qK4G71CqRIm7DmXCheSlDzqLACwJAFOU4xN3eqTO3B4Bm5Wri9Oip
hkwzMgWrDNFx/69ZnGF69g0VP8Qyl4R7d3FZDQIDAQABAoIBAQCzCDYpxybO0Sl3
kFXEuf3FHNRrEr8aA9cPQUHeLuppKV++zG0M8CpaaNqENjHQ8lTDiUE1ETuV7wfD
TpGmWmdTPZMe0B/6c9bYGiickrInbHHamJXAmw1qwh5VEXc8fJqslL2feTEWVoLc
xU0pODfacenjS5W+sE99T0xUrG9hQJMRtNOorMQiUraLl670yIZnzMszDIdd1xdv
4XCuQ5Phnup22/kvByIdiNXPaSY/gOooBTZDUzka+FV3Nn9XXhZoNBnNfk6XgHZw
x9vQvnN+tuDr6RX4g1RPq/u6IhsQO2/OT9wwu74KLdkLFTssGold73uys2WvC0NW
zNFVBuBBAoGBAO6lhTWE2hvt5h7btEY36XgoJbu0k/E7fVgEud2yCdRdQ5ApAHVs
xvol1D3waVKUrRePKq2BhaylwtYACYAow3geMsGrlf4ndlLOQ1z6ByNncJPF3Tr1
lFp025QLijoKmnCq3CdIVPrdhTm44go2usXytobpxS2nB5hZwZfyDju5AoGBANhy
i9vOlRXcLiHpmzAKwFs/jR9D09DUZ6ALm22HvDOsISJS+nR2neun+7HXXHm1Kqyu
w1GA8xaqBnuFfuHP09ZYTNammEROS8dL/5muGCwrfwIrd/H4ELsE0spWOrTlfgY/
GN5WeoXZGAwjiu67AoRkpKIQxnsjEKSNKZQntjn1AoGAOyAdIcZZd2P4iJqsTl1Z
5aAkwR2bLcAsbNs25XtPviKhM51E9NLPdXhb3kCrB3+4ZsbcrwIRCVZEMFrv/6WZ
0C/DKYKGdeJ3CUr7G5UCob3mAWabShk/+S1MnaBCTeEEpHdgdgcQrtqlQEjTD+7B
VXutxz0x0f64/gD22ttotVkCgYAma4a52JyMCc5ChMXgLDhiuhAhuZdynRFbzlOj
iJF2lpo3DoWYgKmdd+7sbW7jx62wg0D2Sa5cmoeWC2cvTAWtKXVSMLYcgc1frfTL
4aQ2yu27g93BnKfTmpKUCeRX0dih4TdX1//dnGBxXym9IILc30R94/5nQx0kKE52
Fup4tQKBgHrDPBIJG3MkA5UIkBPnxE9Ei8V4g/TpYjmC+6JiWkBTQCNZ4A2KKl7S
pwGQwdcqA5OsPbw0T54HwMtDm0ao0b3krb70vBw/xdIAHNe3DCmeOuKelvjDyzr1
ZL6gF557VfKFjz23Hp2PbOYo88BAdX1H1zy0FUZJ7Zh4GbOjgVFQ
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJxnB7QW5ghKwVoe9qmU2Fv26mUbxh4yR98gpenrfczCKEAKag2goRAeWpIoPW6tl8tiPB/VgEoA+31BF0iC7CxDeGXfEqmw76CyZo6kXd4kxVYdl1L9PuWmUg5xevS1tR6JtD2n5z4yAgJ+l0Am9Se4PyCsOZpO69qwFq3g7DqtcjOxBYrNKs/eJAnTF6r6apEiU8/l3CXrpEX52VqWhXGW8b3mLe7nXYSQ2D6wy3VfkpuEd5xBKJykDwraorgbvUKpEibsOZcKF5KUPOosALAkAU5TjE3d6pM7cHgGblauL06KmGTDMyBasM0XH/r1mcYXr2DRU/xDKXhHt3cVkN charles@ultix-mini

Binary file not shown.