Good morning fellow monks.
On purpose, I volunteered to update a deploy script. The current script is a Perl 4 stand-alone script that copies files into their proper deployment locations.
I sold my boss on moving common code into a package, because it would (1) hide and reuse duplicated code, (2) shorten new typical deploy scripts dramatically; (3) potentially reduce accidental errors, (4) introduce such innovations as use strict; and use warnings; and (5) give the systems team a tiny bit of control over code maintainability, as opposed to 'no control' today.
I'm thinking of a package that minimizes the "visual change" of the existing way, but adds a healthy dose of SAFER.
Here's a very typical example. Note the lack of safe practices.
THE WAY IT IS NOW
#!/usr/bin/perl
#---------------------------------------------------------------------
+-------------
# Filename: my_filename_goes_here.pl
#
# This script is executed by the deploy tool as part of the standard
# deploy process. This script moves batch SE work flow batch scripts
+to the correct
# locations where <<we>> expect to find them within the local filesyst
+em.
#
# Date Developer Comment
# ---------- ---------------- -------------------------------
+-------------
# 02-06-2019 R. Eaglestone Initial creation
#---------------------------------------------------------------------
+-------------
use File::Copy;
# Define script-global variables.
$outputDir = "/whatever/data/output";
$executionDir = "/whatever/jobs";
$installDir = "/www/apps/install/path/for/my/process/scripts";
%dirsToDeploy =
(
"$outputDir/boo" => 0777,
"$outputDir/boo/jum" => 0777,
"$executionDir/boo" => 0777,
"$executionDir/boo/jum" => 0777,
);
%pathsToDeploy =
(
"MY_LAUNCHER_11023200099.sh" => '/fancy/deploy/path',
"fileSanity.pl" => '/fancy/deploy/path',
"transferFile.sh" => '/fancy/deploy/path',
);
%filesToDeploy =
(
"MY_LAUNCHER_11023200099.sh" => 0775,
"fileSanity.pl" => 0775,
"transferFile.sh" => 0775,
);
@filesToConvert =
(
"MY_LAUNCHER_11023200099.sh",
"fileSanity.pl",
"transferFile.sh",
);
# This subroutine ensures that all files are present.
sub checkDeployValidity () {
# First, check that the install directory exists.
if ( !(-d $installDir) ) {
return "install directory $installDir was not deployed.";
}
# Then, check that the base execution directory exists.
if ( ! (-d $executionDir) ) {
return "execution directory $executionDir does not exist.";
}
# Next, set permissions on the installation directory.
if ( ! chmod(0775, $installDir) ) {
return "Setting permissions on directory $installDir failed.";
}
# Now, check that all files were deployed.
my @scriptFileNames = sort(keys(%filesToDeploy));
foreach $fileName (@scriptFileNames) {
$currentFile = "$installDir/$fileName";
if ( !(-f $currentFile) ) {
return "file $currentFile was not deployed.";
}
}
# Finally, if all files are present, then return success.
return "";
}
# This subroutine builds any missing directories.
sub setUpDirectoryStructure () {
# Build any subdirectories, if necessary.
my @directoryNames = sort(keys(%dirsToDeploy));
foreach $dirName (@directoryNames) {
# Check whether the directory exists...
if ( -d $dirName ) {
# If so, then set its permissions appropriately.
if ( ! chmod($dirsToDeploy{$dirName}, $dirName) ) {
print "\tunable to do 'chmod $dirsToDeploy{$dirName} $dirName'
+.\n";
}
} elsif ( ! mkdir($dirName, $dirsToDeploy{$dirName}) ) {
print "\tunable to create directory '$dirName'.\n";
}
}
# Finally, return success once all directories exist with proper per
+missions.
return "";
}
# This subroutine removes carriage return characters from specific fil
+es.
sub dosToUnix () {
foreach $fileName (@filesToConvert) {
my $file = "$installDir/$fileName";
my $tempFile = "$file.tmp_dos2Unix";
open(DOS_FILE, "< $file") || return "cannot open $file for re
+ad: $!";
open(UNIX_FILE, "> $tempFile") || return "cannot open $tempFile fo
+r write: $!";
# Remove all carriage return ('\r') characters.
while (<DOS_FILE>) {
s/\r//g;
print UNIX_FILE || return "cannot write to $tempFile: $!";
}
close(UNIX_FILE) || return "cannot close $tempFile: $!";
close(DOS_FILE) || return "cannot close $file: $!";
rename($file, "$file.orig") || return "cannot rename $file to $fil
+e.orig: $!";
rename($tempFile, $file) || return "cannot rename $tempFile to
+$file: $!";
unlink("$file.orig") || return "cannot delete $file.orig:
+$!";
}
return "";
}
# This subroutine copies files from the install dir to the execution d
+ir.
sub copyFilesToTarget () {
my @fileNames = sort(keys(%filesToDeploy));
foreach $fileName (@fileNames) {
my $source = "$installDir/$fileName";
my $path = $pathsToDeploy{$fileName};
my $target = "$path/$fileName";
if ( -f $target) {
chmod(0777, $target) || return "chmod 777 for existing file '$ta
+rget' failed.";
}
copy($source, $target) || return "file copy to '$target' failed.";
chmod($filesToDeploy{$fileName}, $target) || return "chmod for '$t
+arget' failed.";
}
return "";
}
# This subroutine orchestrates the deploy process.
sub main () {
# Start by setting umask to 0 to simplify mkdir commands.
my $oldUMask = umask(0000);
# Next, check that all of the files exist.
my $errorMessage = &checkDeployValidity();
if ( $errorMessage ) {
umask($oldUMask);
die("$0: ERROR - $errorMessage");
}
# Then, set up the execution directory structure.
$errorMessage = &setUpDirectoryStructure();
if ( $errorMessage ) {
umask($oldUMask);
die("$0: ERROR - $errorMessage");
}
# Convert files from DOS format to Unix format.
$errorMessage = &dosToUnix();
if ( $errorMessage ) {
umask($oldUMask);
die("$0: ERROR - $errorMessage");
}
# Now, copy the files over.
$errorMessage = ©FilesToTarget();
if ( $errorMessage ) {
umask($oldUMask);
die("$0: ERROR - $errorMessage");
}
# Finally, restore the old umask value (in case this process is reus
+ed).
umask($oldUMask);
print "Copy succeeded. Job finished successfully.\n";
exit(0);
}
&main ();
THE WAY I'M THINKING IT COULD BE, my knee-jerk gut reaction:
#!/usr/bin/perl
#---------------------------------------------------------------------
+--------------
# Filename: my_filename_goes_here.pl
#
# This script is executed by the deploy tool as part of the standard
# deploy process. This script moves batch SE work flow batch scripts
+to the correct
# locations where <<we>> expect to find them within the local filesyst
+em.
#
# Date Developer Comment
# ---------- ---------------- -------------------------------
+--------------
# 02-06-2019 R. Eaglestone Initial creation
#---------------------------------------------------------------------
+--------------
use DEPLOYER;
use File::Copy;
# Define script-global variables.
DEPLOYER::outputDir("/whatever/data/output");
DEPLOYER::executionDir("/whatever/jobs");
DEPLOYER::installDir("/www/apps/install/path/for/my/process/scripts");
DEPLOYER::dirsToDeploy
(
"$outputDir/boo" => 0777,
"$outputDir/boo/jum" => 0777,
"$executionDir/boo" => 0777,
"$executionDir/boo/jum" => 0777,
);
DEPLOYER::pathsToDeploy
(
"MY_LAUNCHER_11023200099.sh" => '/fancy/deploy/path',
"fileSanity.pl" => '/fancy/deploy/path',
"transferFile.sh" => '/fancy/deploy/path',
);
DEPLOYER::filesToDeploy
(
"MY_LAUNCHER_11023200099.sh" => 0775,
"fileSanity.pl" => 0775,
"transferFile.sh" => 0775,
);
DEPLOYER::filesToConvert
(
"MY_LAUNCHER_11023200099.sh",
"fileSanity.pl",
"transferFile.sh",
);
DEPLOYER::deploy();
Thus, DEPLOYER would use strict and warnings, have all the deployment guts in it, in a common module managed by the systems team, as opposed to the current chaos.
As I said, this is my gut reaction. Before I rush ahead with this, would you guys have any suggestions for me to consider?