Compare commits

..

72 commits

Author SHA1 Message Date
Duncan Ferguson
9431ccc863 Re-release/version bump
Re-release due to poor release upload to CPAN (4.17)
2024-10-19 12:57:45 +01:00
Duncan Ferguson
cc90a9a3fb Run through 'dzil perltidy' 2024-10-17 21:12:23 +01:00
Duncan Ferguson
fea0b80d48
GitHub actions (#161) 2024-10-16 09:21:26 +01:00
Duncan Ferguson
2d39fe46f3 Fix gitactions typos 2024-10-14 23:25:52 +01:00
Duncan Ferguson
6967bceb8b Swap Travis-CI to Github Actions 2024-10-14 23:21:32 +01:00
Duncan Ferguson
a915d3d218 Update perl testing versions in TravisCI 2024-10-14 22:51:43 +01:00
Duncan Ferguson
46c9bfc067 Add in 'hostname_override' configuration
Add in a new configuration option to override the system hostname
rather than rely on DNS (which may not be correctly configured on
the system)

Github issue #158
2024-10-14 22:48:50 +01:00
Duncan Ferguson
4188dc980f
Merge pull request #155 from cqexbesd/ref
Don't check config is a HASH
2024-05-12 08:21:11 +01:00
Andrew Stevenson
4ea91d4e68 Don't check config is a HASH
At some point `$self->config()` started returning a `bless`ed object so
checking it was a `HASH` began to fail, preventing someone using natural
sort. AFAIK the config option always has to behave as a hash so it should be
safe to avoid this test.
2023-07-31 16:40:10 +02:00
Duncan Ferguson
b302a7724f
Merge pull request #149 from GerMalaz/4k_displays_bigger_menu
Bigger menu for 4k (or bigger) displays
2023-06-11 11:40:59 +01:00
Duncan Ferguson
387190e8f6
Merge pull request #138 from babs/override_via_env
Override config via cssh_* environment variables
2023-06-11 11:40:26 +01:00
Duncan Ferguson
618602f496
Merge pull request #150 from tmancill/perl-issue-20103
Don't try to open a directory as the config file
2023-06-11 11:39:50 +01:00
tony mancill
cffe20e5ae Update t/15config.t test note to differentiate from another test 2023-01-04 22:07:41 -08:00
tony mancill
5eae528662 Don't try to open a directory as the config file
This patches load_configs() to check that the $config being opened is
actually a file and not a directory, which was tripping up the tests
that assert that there is an error when the config file cannot be
written because a directory already exists.

Until recently, the attempt to read the directory as a file was being
silently ignored due to a latent bug in Perl; more about that here:

  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1016369

and

  https://github.com/Perl/perl5/pull/20103

This addresses a bug filed against the Debian package for clusterssh
when t/15config.t tests started failing after the Perl bug was fixed.

  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1026735
2023-01-04 22:07:41 -08:00
Gerardo Esteban Malazdrewicz
00d8aa0ebd Bigger menu for 4k (or bigger) displays
Detects screen size based on $xdisplay data.
If 4k or bigger uses Nimbus 14 for the menu.

Fixes #136.
2023-01-04 05:24:00 -04:00
Duncan Ferguson
e11cc83620
Merge pull request #141 from tmancill/minor-typos
address minor typos in manpage for ClusterSSH and ClusterSSH::Host
2021-06-29 08:48:48 +01:00
Duncan Ferguson
70b4731659
Merge pull request #140 from tmancill/startup-vars
warn user when short-circuiting initialisation
2021-06-29 08:47:55 +01:00
tony mancill
4b317108fe
address minor typos in manpage for ClusterSSH and ClusterSSH::Host 2021-06-27 12:23:12 -07:00
tony mancill
0b5b5c8608 warn user when short-circuiting initialisation
See Debian bug report and discussion here:
  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=989679

The bug submitter suggests using a mechanism like the following to
prevent test failures when Tk isn't present:
  5cf873739e/t/config-model-ui.t (L96)
2021-06-27 12:07:49 -07:00
Damien Degois
5ddb7dbe83 Override confuration via environment variable using cssh_ prefix (works with upper and lower case)
Squash commit.
2021-04-01 10:28:09 +02:00
Duncan Ferguson
6cbec687bd Merge branch 'master' of github.com:duncs/clusterssh 2020-06-20 10:33:19 +01:00
Duncan Ferguson
c3a2336b09 Further fix for resolve_names error
Correct a further two method calls
2020-06-20 10:30:48 +01:00
Duncan Ferguson
0505630d15
Merge pull request #133 from pevik/fix-regression-v4.15
helper: Fix missing space separator for ssh_args
2020-05-27 09:15:03 +01:00
Petr Vorel
bf6e9d0648 helper: Fix missing space separator for ssh_args
Docs suggest using ssh_args without space at the end
ssh_args = "-x -o ConnectTimeout=10"

+ remove also trailing space in another line.

Fixes: 82f8845 ("Add in 'command_pre' and 'command_post' configs")

Signed-off-by: Petr Vorel <petr.vorel@gmail.com>
2020-05-22 11:20:30 +02:00
Duncan Ferguson
b35f198f08 v4.15 2020-05-18 08:22:32 +01:00
Duncan Ferguson
208889e36d Mark perms test as TODO
This test appears to be inconsistent and needs further investigation to
work out why
2020-04-21 08:29:12 +01:00
Duncan Ferguson
4674b20fb9 Add lib path to range.t
Some users have picked up on failing tests due to "use lib" not being set
in the range.t test file
2020-04-21 08:25:55 +01:00
Duncan Ferguson
276cab7014 Fix 'Add Host' menu error finding 'resolved_names' 2020-04-19 20:08:07 +01:00
Duncan Ferguson
82f88450d0 Add in 'command_pre' and 'command_post' configs
This allows for running commands before and after the comms method in
the command pipeline, such as setting up python virtual environments
and piping output through other commands
2020-04-18 17:05:00 +01:00
Duncan Ferguson
7fe7c69769 Include all utilies within each man page
Explicitly list each util in the help pages to make it more obvious they
exist
2020-04-18 13:13:47 +01:00
Duncan Ferguson
6ec912aac2 Release 4.14 2019-08-21 21:15:44 +01:00
Duncan Ferguson
dab4fa2237 Add in macro_user_1 .. 4
Add in user macros that can run an external command to pass into each
client terminal session.  Ensure that if no user command is defined that
the expected 'Alt-1' to 'Alt-4' keys are passed into the terminals
instead.

Include docs and examples of how they might be used.
2019-03-28 22:52:03 +00:00
Duncan Ferguson
900d0fabb6
Merge pull request #119 from pevik/fix-typo
doc: Fix typo s/quiting/quitting/
2019-03-17 16:42:57 +00:00
Petr Vorel
e039fef919 doc: Fix typo s/quiting/quitting/
Fixes: #118

Reported-by: Tony Mancill <tmancill@debian.org>
Signed-off-by: Petr Vorel <petr.vorel@gmail.com>
2019-03-16 20:20:02 +01:00
Duncan Ferguson
805f97cd78 Include github issue in changes log 2019-03-16 14:59:08 +00:00
Duncan Ferguson
40079d23d9 Perltidy 2019-03-16 14:56:49 +00:00
Duncan Ferguson
6529bccdbd Correct macro_hostname to be as per the docs
macro_hostname should be the FQDN of the server where cssh is being run
2019-03-16 14:54:31 +00:00
Duncan Ferguson
dd33799eb7 Mark github issue in changes log 2019-03-16 14:40:04 +00:00
Duncan Ferguson
537c4c2572 Add 'auto quit' setting to the File menu
The initial value for "auto quit" is taken from the config file but can
be overridden within the console UI for that session.

Although menu code for "auto close" is added, the functionality does not
work as expected.  This is because the setting is put onto each terminal
when it is opened and is not updated thereafter.
2019-03-16 14:35:16 +00:00
Duncan Ferguson
2712379084 Update docs with version bump 2019-03-16 09:06:05 +00:00
Duncan Ferguson
fb4b90886b Skip release tests unless releasing 2019-03-16 09:04:23 +00:00
Duncan Ferguson
40d0bd4b8f Include generated README in the repository
This is so releases downlaoded directly from github pass tests and
also so the project page has the text available
2019-03-16 08:14:06 +00:00
Duncan Ferguson
73657d2fa3 4.13.2_02 release 2019-01-14 20:06:43 +00:00
Duncan Ferguson
ee3677dcd9 Fix Sort::Naturally error output 2019-01-14 20:05:27 +00:00
Duncan Ferguson
7095383762 More author test prereqs for newer perls
Also mark 'dev' as allowed build failures
2018-12-01 18:44:31 +00:00
Duncan Ferguson
006216faff Force install author repreqs 2018-12-01 18:36:42 +00:00
Duncan Ferguson
49828a49d0 Add author mods to travis config
Add required modules for author testing to the travis build environment
2018-12-01 18:30:26 +00:00
Duncan Ferguson
2fc4516740 Disable author testing 2018-12-01 17:59:07 +00:00
Duncan Ferguson
6fbc2a3eab Amend README generation order 2018-12-01 17:55:57 +00:00
Duncan Ferguson
204048ecc5 Author dependancies
Delare some prereqs used when authoring
2018-12-01 17:47:32 +00:00
Duncan Ferguson
2f5b717671 Add in recommends for travis testing 2018-12-01 17:39:54 +00:00
Duncan Ferguson
30a0817d3c Do not pull in Tk if build/test env vars set
This is to fix an ssue when generating POD on travis servers during
testing
2018-11-25 14:30:03 +00:00
Duncan Ferguson
5016a136d6 Travis tidyups
Amendments attempting to get travis build order working
2018-11-25 13:12:56 +00:00
Duncan Ferguson
e5c33c6e13 Version bump and travis fix
- Amend min version of Getopt::Long for Travis
- Bump the dist version
2018-11-25 13:03:30 +00:00
Duncan Ferguson
e857392130 First round of Dist::Zilla changes
Start process to convert to using Dist::Zilla to make life
easier for both the author and for users
2018-11-25 00:08:31 +00:00
Duncan Ferguson
47fd5237f9 Update to Perl::Tidy 20181117 2018-11-17 22:24:18 +00:00
Duncan Ferguson
27a714ecfa Merge branch 'master' of github.com:duncs/clusterssh 2018-11-17 22:09:30 +00:00
Duncan Ferguson
717e7af776 Fix for 'bad pad value "3m"' error when using Tk 804.034
It appears Tk::Dialog from Tk version 804.034 has a bug in it that was
not in Tk 804.033.  Swap from using Tk::Dialog to Tk::DialogBox to
avoid the bug until it can be reported/fixed upstream..

Github issue #108
2018-11-17 22:07:50 +00:00
Duncan Ferguson
09f2671d8e
Merge pull request #107 from bmwiedemann/worldwritable
Do not make files world writable
2018-04-05 12:57:37 +01:00
Bernhard M. Wiedemann
0acfe66a99 Do not make files world writable
If we can chmod it, we own the file,
so we only need a writable-bit for the owner, not for everybody.

The permissions are changed back soon after, but it creates a small window
for local attackers to insert their stuff into our build results.
2018-04-05 06:37:00 +02:00
Duncan Ferguson
7670b0be39 Pull in all fixes from 4.13.x 2018-03-15 22:09:44 +00:00
Duncan Ferguson
4599f3df22 Set minimum perl version to 5.8.4 2017-12-29 11:32:47 +00:00
Duncan Ferguson
f27c42c795 Improve test coverage 2017-12-27 16:35:35 +00:00
Duncan Ferguson
c807b52129 Improve test coverage 2017-12-27 13:44:31 +00:00
Duncan Ferguson
5615bbc5b1 Update copyright year to 2018 2017-12-27 11:03:52 +00:00
Duncan Ferguson
b9731d0e35 Fix tests
- perltidy
- add pod to new modules
- code fix for accessing config via Base.pm
- fix some minor typos
2017-12-27 10:58:28 +00:00
Duncan Ferguson
0fe831e25f Update Changes file 2017-12-27 10:29:11 +00:00
Duncan Ferguson
3816e735b1 Merge branch 'module_window'
Moving all Tk code into a separate module
2017-12-27 10:25:26 +00:00
Duncan Ferguson
4dcba4d693 Apply console position fix 2017-12-27 10:22:07 +00:00
Duncan Ferguson
3a7e832855 Move all Tk code into its own module 2017-12-27 10:19:53 +00:00
Duncan Ferguson
3d571b2801 Start reworking Tk into a module 2017-12-27 10:17:46 +00:00
Duncan Ferguson
7163916a99 Mark new dev version (4.13_01) 2017-12-27 10:16:29 +00:00
47 changed files with 3005 additions and 2923 deletions

68
.github/workflows/dzil_tester.yml vendored Normal file
View file

@ -0,0 +1,68 @@
name: CI test builds
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
perl-job:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
perl-version:
- 'devel'
- 'latest'
- '5.40'
- '5.38'
- '5.36'
- '5.34'
- '5.32'
- '5.30'
- '5.28'
- '5.26'
- '5.24'
- '5.22'
- '5.20'
- '5.18'
- '5.16'
include:
- perl-version: '5.38'
os: ubuntu-latest
coverage: true
container:
image: perldocker/perl-tester:${{ matrix.perl-version }}
name: Perl ${{ matrix.perl-version }}
steps:
- uses: actions/checkout@main
- name: Amend PATH
run: echo "${GITHUB_WORKSPACE}/t/bin" >> $GITHUB_PATH
- name: Current env
run: env
- name: Perl info
run: perl -V
- name: CPAN test modules
run: cpanm -n Pod::Coverage::TrustPod Test::Perl::Critic Test::Pod::Coverage Test::Pod Test::Trap
- name: CPAN build modules
run: cpanm -n Tk X11::Protocol X11::Protocol::Other
- name: Initial Build
run: perl Build.PL
- name: Build the MANIFEST
run: perl Build manifest
- name: Test suite
if: ${{ !matrix.coverage }}
run: perl Build test
env:
RELEASE_TESTING: 1
AUTHOR_TESTING: 1
- name: Coverage tests
if: ${{ matrix.coverage }}
run: perl Build test
env:
COVERAGE: 1
RELEASE_TESTING: 1
AUTHOR_TESTING: 1

6
.gitignore vendored
View file

@ -1,7 +1,12 @@
/App-*
*.bak
/bin
/blib/
/_build/
/.build/
/Build
Build.PL.orig
Build.PL.x
/cover_db/
/Makefile
/MANIFEST.bak
@ -9,5 +14,4 @@
/MYMETA.yml
/pm_to_blib
*.swp
*.bak
*.tar.gz

View file

@ -1,30 +0,0 @@
language: perl
perl:
- blead
- dev
# No clean build due to removal of '.' from lib path
# - 5.26
- 5.24
- 5.22
- 5.20
- 5.18
- 5.16
- 5.14
- 5.12
- 5.10
# stopping builds; is anyone really still using this version?
# - 5.8
matrix:
include:
- perl: 5.24
env: COVERAGE=1
allow_failures:
- perl: blead
- perl: blead-thr
sudo: false
env:
global:
- RELEASE_TESTING=1
- AUTHOR_TESTING=1
before_install:
- eval $(curl https://travis-perl.github.io/init) --auto

191
Build.PL
View file

@ -1,169 +1,38 @@
use strict;
use warnings;
use Cwd;
use lib 'inc';
use Module::Build;
require Module::Build;
# touch README
open( my $fh, '>>', 'README' );
close($fh);
my %project_info = (
tracker => 'https://github.com/duncs/clusterssh/issues',
repository => 'http://github.com/duncs/clusterssh',
homepage => 'http://github.com/duncs/clusterssh/wiki',
ci => 'https://travis-ci.org/duncs/clusterssh',
coverage => 'https://coveralls.io/github/duncs/clusterssh',
);
my $class = Module::Build->subclass(
class => "Module::Build::Custom",
code => qq{
my \%project_info = (
tracker => '$project_info{tracker}',
homepage => '$project_info{homepage}',
repository => '$project_info{repository}',
ci => '$project_info{ci}',
coverage => '$project_info{coverage}',
);
} . q{
# don't check for errors; 'build_requires' should get this sorted
eval {
require File::Slurp;
require CPAN::Changes;
};
sub ACTION_email {
my ($self, @args) = @_;
# Make sure all tests pass first
$self->depends_on("test");
print "Use '--changes <N>' to define how many to output. Default: 1", $/;
my $change_count = $self->args('changes') || 1;
my @changes = CPAN::Changes->load( 'Changes' )->releases;
if($changes[-1]->date =~ m/^0000/) {
die '#' x 40, $/, ' ' x 3, "FATAL: 'Changes' date not updated",$/,'#' x 40, $/;
}
print $/;
print 'Subject: ClusterSSH ', $self->dist_version, ' release', $/;
print $/;
foreach my $change ( 1 .. $change_count ) {
print $changes[ 0 - $change]->serialize;
}
my $v=$self->dist_version;
print <<"EOF";
==========
Home page: $project_info{homepage},
Bug Reports and Issues: $project_info{tracker}
Project Repository: $project_info{repository}
Full Changes log: $project_info{repository}/blob/release-$v/Changes
Automated Testing: $project_info{ci}
Automated test coverage: $project_info{coverage}
CPAN release: http://search.cpan.org/~duncs/App-ClusterSSH-$v
SF release: http://sourceforge.net/projects/clusterssh/files/2.%20ClusterSSH%20Series%204/App-ClusterSSH-${v}.tar.gz/download
==========
EOF
return $self;
}
sub ACTION_dist {
my ($self, @args) = @_;
print "Creating README", $/;
qx{ $^X bin_PL/cssh --generate-pod | pod2text > README };
$self->SUPER::ACTION_dist;
}
sub ACTION_clean {
my ($self, @args) = @_;
for my $file (keys %{ $self->script_files } ) {
if( -e $file) {
print "Removing '$file'",$/;
unlink $file;
}
}
$self->SUPER::ACTION_clean;
}
},
);
my $build = $class->new(
meta_merge => {
resources => {
Repository => [
#'http://clusterssh.git.sourceforge.net/',
$project_info{repository},
],
bugtracker => $project_info{tracker},
homepage => $project_info{homepage},
coverage => $project_info{coverage},
},
},
module_name => 'App::ClusterSSH',
license => 'perl',
dist_author => q{Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>},
dist_version_from => 'lib/App/ClusterSSH.pm',
requires => {
'version' => '0.77',
'Tk' => '800.022',
'X11::Protocol' => '0.56',
'X11::Protocol::WM' => '0',
'Locale::Maketext' => 0,
'Exception::Class' => '1.31',
'Try::Tiny' => 0,
'Getopt::Long' => 0,
'File::Path' => 0,
'File::Glob' => 0,
},
build_requires => {
'Test::Pod::Coverage' => 0,
'Test::Pod' => 0,
'Test::Trap' => 0,
'Readonly' => 0,
'File::Which' => 0,
'File::Temp' => 0,
'Test::DistManifest' => 0,
'Test::Differences' => 0,
'CPAN::Changes' => 0.27,
'File::Slurp' => 0,
'Test::PerlTidy' => 0,
'Perl::Tidy' => 20180220,
},
recommends => { 'Sort::Naturally' => 0, },
configure_requires => { 'Module::Build' => 0, },
add_to_cleanup => ['App-ClusterSSH-*'],
create_makefile_pl => 'traditional',
script_files => [
'bin/cssh',
'bin/csftp',
'bin/ccon',
'bin/crsh',
'bin/ctel',
'bin/clusterssh_bash_completion.dist'
my %module_build_args = (
module_name => 'App::ClusterSSH',
dist_abstract => "Cluster administration tool",
##{ $plugin->get_prereqs(1) ##}
##{ $plugin->get_default('share_dir') ##}
script_files => [
'bin/cssh', 'bin/csftp',
'bin/ccon', 'bin/crsh',
'bin/ctel', 'bin/clusterssh_bash_completion.dist'
],
get_options => { changes => { type => '=s' }, },
PL_files => {
PL_files => {
'bin_PL/_build_docs' => [
'bin/cssh',
'bin/csftp',
'bin/ccon',
'bin/crsh',
'bin/ctel',
'bin/clusterssh_bash_completion.dist'
'bin/cssh', 'bin/csftp',
'bin/ccon', 'bin/crsh',
'bin/ctel', 'bin/clusterssh_bash_completion.dist'
],
},
);
$build->create_build_script;
unless ( eval { Module::Build->VERSION(0.4004) } ) {
my $tr = delete $module_build_args{test_requires};
my $br = $module_build_args{build_requires};
for my $mod ( keys %$tr ) {
if ( exists $br->{$mod} ) {
$br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
}
else {
$br->{$mod} = $tr->{$mod};
}
}
} # end unless Module::Build is 0.4004 or newer
my $builder = Module::Build->new(%module_build_args);
$builder->create_build_script;

37
Changes
View file

@ -1,3 +1,40 @@
Revision history for {{$dist->name}}
4.18 2024-10-19 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Re-release due to poor release upload to CPAN
4.17 2024-10-16 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Swap the hostname lookup macro from DNS to using the system hostname (Github issue #158)
- Swap from using Travis-CI to Github Actions
- Fix tests on perl 5.38 and 5.40 (Github Issue #153)
4.16 2020-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Further fix for 'resolve_names' error when adding hosts via the UI
- Fix missing space separator for ssh_args (thanks to Petr Vorel)
4.15 2020-05-18 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Include all utilies within each man page
- Add in 'command_pre' and 'command_post' configuration options
- Fix 'Add Host' menu error finding 'resolved_names'
- Ensure lib path is added to range tests to find the libraries
- Mark permission test as TODO as it appears to be inconsistent
4.14 2019-08-21 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Include README within the repository, not just created tar.gz files
- Add 'autoquit' setting to 'File' menu (Github issue #114)
- Correct macro_hostname to be the FQDN of the server where cssh is being run (Github issue #116)
- Add in user defined macros
4.13.2_02 2019-01-14 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Fix Getopt-Long minimum version
- Fix excess test output when Sort::Naturally isn't installed
4.13.2_01 2018-11-24 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Move all Tk code into its own module as-is
- Fix for 'bad pad value "3m"' error when using Tk 804.034
- Update to Perl::Tidy 20181117
- Convert to using Dist::Zilla
4.13.2 2018-03-14 Duncan Ferguson <duncan_ferguson@user.sf.net>
- Fix for running builds in parallel
- Improvements to SUPPORT and REPORTING BUGS sections in documentation

63
INSTALL
View file

@ -1,63 +0,0 @@
App-ClusterSSH
The is the Perl application bundle for ClusterSSH (a.k.a cssh), formally
a GNU tools based project.
ClusterSSH is a tool for making the same change on multiple servers at
the same time. The 'cssh' command opens an administration console and
an xterm to all specified hosts. Any text typed into the administration
console is replicated to all windows. All windows may also be typed into
directly.
This tool is intended for (but not limited to) cluster administration
where the same configuration or commands must be run on each node
within the cluster. Performing these commands all at once via this
tool ensures all nodes are kept in sync.
For more information, go to https://github.com/duncs/clusterssh
INSTALLATION
To install this module, run the following commands:
perl Build.PL
./Build
./Build test
./Build install
SUPPORT AND DOCUMENTATION
After installing, you can find documentation for this module with the
perldoc command.
perldoc cssh
or (if your MANPATH is set up appropriately)
man cssh
You can also look for information at:
Web site and GitHub project page
https://github.com/duncs/clusterssh
Project support area
https://github.com/duncs/clusterssh/issues
AnnoCPAN, Annotated CPAN documentation
http://annocpan.org/dist/App-ClusterSSH
CPAN Ratings
http://cpanratings.perl.org/d/App-ClusterSSH
Search CPAN
http://search.cpan.org/dist/App-ClusterSSH/
COPYRIGHT AND LICENCE
Copyright (C) 1999-2016 Duncan Ferguson
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.

View file

@ -1,60 +0,0 @@
AUTHORS
bin_PL/_build_docs
bin_PL/ccon
bin_PL/clusterssh_bash_completion.dist
bin_PL/crsh
bin_PL/cscp.x
bin_PL/csftp
bin_PL/cssh
bin_PL/ctel
Build.PL
Changes
INSTALL
lib/App/ClusterSSH/Base.pm
lib/App/ClusterSSH/Cluster.pm
lib/App/ClusterSSH/Config.pm
lib/App/ClusterSSH/Getopt.pm
lib/App/ClusterSSH/Helper.pm
lib/App/ClusterSSH/Host.pm
lib/App/ClusterSSH/L10N/en.pm
lib/App/ClusterSSH/L10N.pm
lib/App/ClusterSSH.pm
lib/App/ClusterSSH/Range.pm
Makefile.PL
MANIFEST
MANIFEST.SKIP
META.json
META.yml
README
t/00-load.t
t/01l10n.t
t/02base.t
t/05getopts.t
t/10host_ssh_config
t/10host_ssh_include
t/10host.t
t/15config.t
t/15config.t.file1
t/15config.t.file2
t/15config.t.file3
t/20helper.t
t/30cluster.cannot_read
t/30cluster.file1
t/30cluster.file2
t/30cluster.file3
t/30cluster.t
t/30cluster.tag1
t/80clusterssh.t
t/bin/xterm
t/boilerplate.t
t/changes.t
t/external_cluster_command
THANKS
t/manifest.t
TODO
t/perltidyrc
t/perltidy.t
t/pod-coverage.t
t/pod.t
t/range.t
.travis.yml

View file

@ -1,19 +0,0 @@
^App-ClusterSSH-.*
.*\.bak$
^bin/
^blib/
^_build/
^Build$
^Build.run$
^cover_db/
^.git/
^.gitignore
^Makefile$
^Makefile.old$
^MANIFEST\.bak$
MYMETA.json
MYMETA.yml
pm_to_blib
.*\.swp$
^TOAD$
^WIP_TASKS$

111
META.json
View file

@ -1,111 +0,0 @@
{
"abstract" : "A container for functions of the ClusterSSH programs",
"author" : [
"Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>"
],
"dynamic_config" : 1,
"generated_by" : "Module::Build version 0.4224",
"license" : [
"perl_5"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
},
"name" : "App-ClusterSSH",
"prereqs" : {
"build" : {
"requires" : {
"CPAN::Changes" : "0.27",
"File::Slurp" : "0",
"File::Temp" : "0",
"File::Which" : "0",
"Perl::Tidy" : "20180220",
"Readonly" : "0",
"Test::Differences" : "0",
"Test::DistManifest" : "0",
"Test::PerlTidy" : "0",
"Test::Pod" : "0",
"Test::Pod::Coverage" : "0",
"Test::Trap" : "0"
}
},
"configure" : {
"requires" : {
"Module::Build" : "0"
}
},
"runtime" : {
"recommends" : {
"Sort::Naturally" : "0"
},
"requires" : {
"Exception::Class" : "1.31",
"File::Glob" : "0",
"File::Path" : "0",
"Getopt::Long" : "0",
"Locale::Maketext" : "0",
"Tk" : "800.022",
"Try::Tiny" : "0",
"X11::Protocol" : "0.56",
"X11::Protocol::WM" : "0",
"version" : "0.77"
}
}
},
"provides" : {
"App::ClusterSSH" : {
"file" : "lib/App/ClusterSSH.pm",
"version" : "v4.13.2"
},
"App::ClusterSSH::Base" : {
"file" : "lib/App/ClusterSSH/Base.pm",
"version" : "0.02"
},
"App::ClusterSSH::Cluster" : {
"file" : "lib/App/ClusterSSH/Cluster.pm",
"version" : "0.01"
},
"App::ClusterSSH::Config" : {
"file" : "lib/App/ClusterSSH/Config.pm",
"version" : "0.02"
},
"App::ClusterSSH::Getopt" : {
"file" : "lib/App/ClusterSSH/Getopt.pm",
"version" : "0.01"
},
"App::ClusterSSH::Helper" : {
"file" : "lib/App/ClusterSSH/Helper.pm",
"version" : "0.02"
},
"App::ClusterSSH::Host" : {
"file" : "lib/App/ClusterSSH/Host.pm",
"version" : "0.03"
},
"App::ClusterSSH::L10N" : {
"file" : "lib/App/ClusterSSH/L10N.pm"
},
"App::ClusterSSH::L10N::en" : {
"file" : "lib/App/ClusterSSH/L10N/en.pm"
},
"App::ClusterSSH::Range" : {
"file" : "lib/App/ClusterSSH/Range.pm"
}
},
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"web" : "https://github.com/duncs/clusterssh/issues"
},
"homepage" : "http://github.com/duncs/clusterssh/wiki",
"license" : [
"http://dev.perl.org/licenses/"
],
"x_Repository" : [
"http://github.com/duncs/clusterssh"
],
"x_coverage" : "https://coveralls.io/github/duncs/clusterssh"
},
"version" : "v4.13.2",
"x_serialization_backend" : "JSON::PP version 2.94"
}

View file

@ -1,76 +0,0 @@
---
abstract: 'A container for functions of the ClusterSSH programs'
author:
- 'Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>'
build_requires:
CPAN::Changes: '0.27'
File::Slurp: '0'
File::Temp: '0'
File::Which: '0'
Perl::Tidy: '20180220'
Readonly: '0'
Test::Differences: '0'
Test::DistManifest: '0'
Test::PerlTidy: '0'
Test::Pod: '0'
Test::Pod::Coverage: '0'
Test::Trap: '0'
configure_requires:
Module::Build: '0'
dynamic_config: 1
generated_by: 'Module::Build version 0.4224, CPAN::Meta::Converter version 2.150010'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: App-ClusterSSH
provides:
App::ClusterSSH:
file: lib/App/ClusterSSH.pm
version: v4.13.2
App::ClusterSSH::Base:
file: lib/App/ClusterSSH/Base.pm
version: '0.02'
App::ClusterSSH::Cluster:
file: lib/App/ClusterSSH/Cluster.pm
version: '0.01'
App::ClusterSSH::Config:
file: lib/App/ClusterSSH/Config.pm
version: '0.02'
App::ClusterSSH::Getopt:
file: lib/App/ClusterSSH/Getopt.pm
version: '0.01'
App::ClusterSSH::Helper:
file: lib/App/ClusterSSH/Helper.pm
version: '0.02'
App::ClusterSSH::Host:
file: lib/App/ClusterSSH/Host.pm
version: '0.03'
App::ClusterSSH::L10N:
file: lib/App/ClusterSSH/L10N.pm
App::ClusterSSH::L10N::en:
file: lib/App/ClusterSSH/L10N/en.pm
App::ClusterSSH::Range:
file: lib/App/ClusterSSH/Range.pm
recommends:
Sort::Naturally: '0'
requires:
Exception::Class: '1.31'
File::Glob: '0'
File::Path: '0'
Getopt::Long: '0'
Locale::Maketext: '0'
Tk: '800.022'
Try::Tiny: '0'
X11::Protocol: '0.56'
X11::Protocol::WM: '0'
version: '0.77'
resources:
Coverage: https://coveralls.io/github/duncs/clusterssh
Repository:
- http://github.com/duncs/clusterssh
bugtracker: https://github.com/duncs/clusterssh/issues
homepage: http://github.com/duncs/clusterssh/wiki
license: http://dev.perl.org/licenses/
version: v4.13.2
x_serialization_backend: 'CPAN::Meta::YAML version 0.016'

View file

@ -1,51 +0,0 @@
# Note: this file was auto-generated by Module::Build::Compat version 0.4224
use ExtUtils::MakeMaker;
WriteMakefile
(
'NAME' => 'App::ClusterSSH',
'VERSION_FROM' => 'lib/App/ClusterSSH.pm',
'PREREQ_PM' => {
'CPAN::Changes' => '0.27',
'Exception::Class' => '1.31',
'File::Glob' => 0,
'File::Path' => 0,
'File::Slurp' => 0,
'File::Temp' => 0,
'File::Which' => 0,
'Getopt::Long' => 0,
'Locale::Maketext' => 0,
'Perl::Tidy' => 20180220,
'Readonly' => 0,
'Test::Differences' => 0,
'Test::DistManifest' => 0,
'Test::PerlTidy' => 0,
'Test::Pod' => 0,
'Test::Pod::Coverage' => 0,
'Test::Trap' => 0,
'Tk' => '800.022',
'Try::Tiny' => 0,
'X11::Protocol' => '0.56',
'X11::Protocol::WM' => '0',
'version' => '0.77'
},
'INSTALLDIRS' => 'site',
'EXE_FILES' => [
'bin/ccon',
'bin/clusterssh_bash_completion.dist',
'bin/crsh',
'bin/csftp',
'bin/cssh',
'bin/ctel'
],
'PL_FILES' => {
'bin_PL/_build_docs' => [
'bin/cssh',
'bin/csftp',
'bin/ccon',
'bin/crsh',
'bin/ctel',
'bin/clusterssh_bash_completion.dist'
]
}
)
;

74
README
View file

@ -2,7 +2,7 @@ NAME
cssh - Cluster administration tool
VERSION
This documentation is for version: 4.13.2
This documentation is for version: 4.18
SYNOPSIS
cssh [-a '<command>'] [-K <seconds>] [-q] [-c '<filename>'] [-x <cols>]
@ -12,6 +12,14 @@ SYNOPSIS
[-t '<STRING>'] [-g] [-T '<title>'] [-u] [-?] [-A] [-l '<username>']
[-v]
RELATED
Also see the individual man pages for each of these utilities
ccon - Use 'console' as the communication method
crsh - Use 'rsh' as the communication method
csftp - Use 'sftp' as the communication method
ctel - Use 'telnet' as the communication method
DESCRIPTION
The command opens an administration console and an xterm to all
specified hosts. Any text typed into the administration console is
@ -83,8 +91,8 @@ OPTIONS
Number of seconds to wait before closing finished terminal windows.
--autoquit, -q
Toggle automatically quiting after the last client window has closed
(overriding the config file).
Toggle automatically quitting after the last client window has
closed (overriding the config file).
--cluster-file '<filename>', -c '<filename>'
Use supplied file as additional cluster file (see also "FILES").
@ -223,6 +231,13 @@ KEY SHORTCUTS
Alt-u
Paste in the username for the connection
Alt-1
Alt-2
Alt-3
Alt-4
Run the matching user defined macro on the server and send the
output to the client
EXAMPLES
Open up a session to 3 servers
$ cssh server1 server2 server3
@ -331,6 +346,21 @@ FILES
Enable or disable alternative algorithm for calculating terminal
positioning.
command_pre =
command_post =
Add extra commands around the communication method. For example:
command_pre= . $HOME/virtualenvs/default/bin/active ;
command_post= | ct
would allow for using Python virtual envronments and then piping
all shell output through "chromaterm" for syntax highlighting.
Note: you must use appropriate command separators/terminators to
keep the meaning of the command pipline (such as ";" and "|"
between commands).
These are not put through macro parsing.
comms = ssh
Sets the default communication method (initially taken from the
name of the program, but can be overridden here).
@ -418,14 +448,52 @@ FILES
Default key sequence to send username to client. See "KEY
SHORTCUTS" for more information.
key_user_1 = Alt-1
key_user_2 = Alt-2
key_user_3 = Alt-3
key_user_4 = Alt-4
Default key sequence to send user defined macros to client. If
the matching macro_user_1 macro is undefined, the sequence is
passed straight to the terminal. See "KEY SHORTCUTS" for more
information.
macro_servername = %s
macro_hostname = %h
macro_username = %u
macro_newline = %n
macro_version = %v
macro_user_1 = %1
macro_user_2 = %2
macro_user_3 = %3
macro_user_4 = %4
Change the replacement macro used when either using a 'Send'
menu item, or when pasting text into the main console.
macro_user_1_command =
macro_user_2_command =
macro_user_3_command =
macro_user_4_command =
User defined macros - the macro is run through the shell on the
server and the output is sent to the client. For example,
"macro_user_1_command=echo echo macro_user_1"
would send the text C<echo macro_user_1> into the terminal session.
"macro_user_1_command=env | grep CSSH"
would send the CSSH environment variables to the client.
The following environment variables are set in the shell of the
macro process
"CSSH_SERVERNAME"
"CSSH_HOSTNAME"
"CSSH_USERNAME"
"CSSH_CONNECTION_STRING"
"CSSH_CONNECTION_PORT"
"CSSH_VERSION"
macros_enabled = yes
Enable or disable macro replacement. Note: this affects all the
"macro_*" variables above.

1
THANKS
View file

@ -48,3 +48,4 @@ Bill Rushmore
Ankit Vadehra
Azenet
Markus Frosch (lazyfrosch)
Petr Vorel

View file

View file

@ -1,46 +1,47 @@
#!/usr/bin/env perl
use 5.008.004;
use strict;
use warnings;
use FindBin qw($Bin $Script);
use File::Basename;
my $bindir="bin";
my $bindir = "bin";
if(! -d $bindir) {
if ( !-d $bindir ) {
mkdir $bindir || die "Could not mkdir $bindir: $!";
}
print "Using perl binary: $^X",$/;
print "Using perl version $^V",$/;
print "Using perl binary: $^X", $/;
print "Using perl version $^V", $/;
for my $dest (@ARGV) {
my $source=$Bin.'/'.basename($dest);
my $source = $Bin . '/' . basename($dest);
next if($source =~ m/$Script/);
next if($source =~ m/\.x$/);
next if ( $source =~ m/$Script/ );
next if ( $source =~ m/\.x$/ );
print "Generating: $source",$/;
print "Generating: $source", $/;
if(-f $dest) {
chmod(0777, $dest) || die "Could not chmod $dest for removing: $!";
if ( -f $dest ) {
chmod( 0755, $dest ) || die "Could not chmod $dest for removing: $!";
}
open(my $sfh, '<', $source) || die "Could not open $source for reading: $!";
open(my $dfh, '>', $dest ) || die "Could not open $dest for writing: $!";
print $dfh $_ while(<$sfh>);
open( my $sfh, '<', $source )
|| die "Could not open $source for reading: $!";
open( my $dfh, '>', $dest ) || die "Could not open $dest for writing: $!";
print $dfh $_ while (<$sfh>);
close($sfh);
if($source !~ m/clusterssh_bash_completion.dist/) {
if ( $source !~ m/clusterssh_bash_completion.dist/ ) {
print $dfh "\n\n__END__\n\n";
my $pod= qx{ $^X $source --generate-pod };
die "Failed to generate pod" if($?);
my $pod = qx{ $^X $source --generate-pod };
die "Failed to generate pod" if ($?);
print $dfh $pod;
}
close($dfh);
chmod(0555, $dest) || die "Could not chmod $dest: $!";
chmod( 0555, $dest ) || die "Could not chmod $dest: $!";
}

View file

@ -1,4 +1,5 @@
#!/usr/bin/env perl
use 5.008.004;
use strict;
use warnings;
@ -14,7 +15,9 @@ my $app = App::ClusterSSH->new();
$app->add_option(
spec => 'master|M=s',
help => $app->loc("The console client program polls master as the primary server, rather than the default set at compile time (typically ``console'')."),
help => $app->loc(
"The console client program polls master as the primary server, rather than the default set at compile time (typically ``console'')."
),
);
$app->run();

View file

@ -1,4 +1,5 @@
#!/usr/bin/env perl
use 5.008.004;
use strict;
use warnings;

View file

@ -1,4 +1,5 @@
#!/usr/bin/env perl
use 5.008.004;
use strict;
use warnings;

View file

@ -1,4 +1,5 @@
#!/usr/bin/env perl
use 5.008.004;
use strict;
use warnings;

View file

@ -1,4 +1,5 @@
#!/usr/bin/env perl
use 5.008.004;
use strict;
use warnings;

74
dist.ini Normal file
View file

@ -0,0 +1,74 @@
name = App-ClusterSSH
author = Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>
license = Perl_5
copyright_holder = Duncan Ferguson
copyright_year = 2018
[Git::Check]
[GatherDir]
[MetaYAML]
[ModuleBuild::Custom]
mb_class = App::ClusterSSH:Build
[InstallGuide]
[License]
[PruneCruft]
[PruneFiles]
match = ^bin/
match = \.bak$
match = ^Build\.PL\.
[ManifestSkip]
[Manifest]
[TestRelease]
[ConfirmRelease]
[UploadToCPAN]
; for later
;[Twitter]
[EmailNotify]
to = duncan_j_ferguson@yahoo.co.uk
from = duncan_j_ferguson@yahoo.co.uk
[CheckChangeLog]
[PerlTidy]
perltidyrc = t/perltidyrc
; Need to decide how to do this automatically at some point
[VersionFromModule]
;[Git::NextVersion]
;[AutoVersion]
[AutoPrereqs]
[PkgVersion]
[NextRelease]
[Git::Commit]
[Git::Tag]
[Git::Push]
; optional prereqs - only used if they are installed
[Prereqs / RuntimeRecommends]
Sort::Naturally = 1.03
; Author prereqs
; authordep Pod::Coverage::TrustPod
; authordep Test::CPAN::Changes
[MetaResources]
homepage = http://github.com/duncs/clusterssh/wiki
bugtracker.web = https://github.com/duncs/clusterssh/issues
repository.web = http://github.com/duncs/clusterssh
repository.type = git
; these two custom ones cause errors
;Ci.web = https://travis-ci.org/duncs/clusterssh
;Coverage.web = https://coveralls.io/github/duncs/clusterssh
[ExtraTests]
; Disabled for the moment
;[Test::Perl::Critic]
[PodCoverageTests]
[PodSyntaxTests]
[Run::BeforeBuild]
run = bin_PL/cssh --generate-pod | pod2text > README

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,34 @@
package App::ClusterSSH::Base;
use warnings;
use strict;
package App::ClusterSSH::Base;
# ABSTRACT: App::ClusterSSH::Base - Base object provding utility functions
=head1 SYNOPSIS
use base qw/ App::ClusterSSH::Base /;
# in object new method
sub new {
( $class, $arg_ref ) = @_;
my $self = $class->SUPER::new($arg_ref);
return $self;
}
=head1 DESCRIPTION
Base object to provide some utility functions on objects - should not be
used directly
=cut
use Carp;
use App::ClusterSSH::L10N;
use Exception::Class (
use Module::Load;
use Exception::Class 1.31 (
'App::ClusterSSH::Exception',
'App::ClusterSSH::Exception::Config' => {
fields => 'unknown_config',
@ -16,10 +39,6 @@ use Exception::Class (
'App::ClusterSSH::Exception::Getopt',
);
# Don't use SVN revision as it can cause problems
use version;
our $VERSION = version->new('0.02');
my $debug_level = $ENV{CLUSTERSSH_DEBUG} || 0;
our $language = 'en';
our $language_handle;
@ -142,9 +161,21 @@ sub config {
);
}
return $self->{parent}->{config}
if $self->{parent}
&& ref $self->{parent} eq "HASH"
&& $self->{parent}->{config};
return $app_configuration;
}
sub options {
my ($self) = @_;
return $self->{parent}->{options}
if $self->{parent} && $self->{parent}->{options};
return;
}
sub set_config {
my ( $self, $config ) = @_;
@ -270,29 +301,33 @@ sub parent {
return $self->{parent};
}
1;
sub sort {
my $self = shift;
=pod
# if the user has asked for natural sorting we need to include an extra
# module
my $config = $self->config();
=head1 NAME
App::ClusterSSH::Base - Base object provding utility functions
=head1 SYNOPSIS
use base qw/ App::ClusterSSH::Base /;
# in object new method
sub new {
( $class, $arg_ref ) = @_;
my $self = $class->SUPER::new($arg_ref);
return $self;
# Make sure the configuration object has been set correctly before
# referencing anything
if ( ref $config eq "HASH" && $config->{'use_natural_sort'} ) {
eval { Module::Load::load('Sort::Naturally'); };
if ($@) {
warn(
"natural sorting requested but unable to load Sort::Naturally: $@\n"
);
}
else {
my $sort = sub { Sort::Naturally::nsort(@_) };
return $sort;
}
}
=head1 DESCRIPTION
my $sort = sub { sort @_ };
return $sort;
}
Base object to provide some utility functions on objects - should not be
used directly
1;
=head1 METHODS
@ -338,11 +373,15 @@ a wrapper to maketext in Locale::Maketext
Output text on STDOUT.
=item $ovj->parent;
=item $obj->parent;
Reutrned the object that is the parent of this one, if it was set when the
Returned the object that is the parent of this one, if it was set when the
object was created
=item %obj->options;
Accessor to configured options, if it is set up by this point
=item $obj->exit;
Stub to allow program to exit neatly from wherever in the code
@ -356,27 +395,14 @@ hasnt been called
Set the config to the given value - croaks if has already been called
=item $sort = $obj->sort
Code reference used to sort lists; if configured (and installed) use
Sort;:Naturally, else use perl sort
=item %results = $obj->load_file( filename => '/path/to/file', type => '(cluster|config}' )
Load in the specified file and return a hash, parsing the file depending on
wther it is a config file (key = value) or cluster file (key value)
=back
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -1,13 +1,20 @@
package App::ClusterSSH::Cluster;
use strict;
use warnings;
use version;
our $VERSION = version->new('0.01');
package App::ClusterSSH::Cluster;
# ABSTRACT: App::ClusterSSH::Cluster - Object representing cluster configuration
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=cut
use Carp;
use Try::Tiny;
use Try::Tiny 0.28;
use English qw( -no_match_vars );
use base qw/ App::ClusterSSH::Base /;
@ -80,7 +87,7 @@ sub _run_external_clusters {
$self->debug( 3, 'Running tags through external command' );
$self->debug( 4, 'External command: ', $external_command );
$self->debug( 3, 'Args ', join( ',', @args ) );
$self->debug( 3, 'Args ', join( ',', @args ) );
my $command = "$external_command @args";
@ -287,18 +294,6 @@ sub dump_tags {
1;
=pod
=head1 NAME
App::ClusterSSH::Cluster - Object representing cluster configuration
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=head1 METHODS
=over 4
@ -365,21 +360,3 @@ Returns a hash of all tag data.
Use shell expansion against each item in @items, where $type is either 'node', or 'tag' and $name is the node or tag name. These attributes are presented to the user in the event of an issue with the expanion to track down the source.
=back
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -1,10 +1,17 @@
package App::ClusterSSH::Config;
use strict;
use warnings;
use version;
our $VERSION = version->new('0.02');
package App::ClusterSSH::Config;
# ABSTRACT: ClusterSSH::Config - Object representing application configuration
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=cut
use Carp;
use Try::Tiny;
@ -42,6 +49,10 @@ my %default_config = (
key_macros_enable => "Alt-p",
key_paste => "Control-v",
key_username => "Alt-u",
key_user_1 => "Alt-1",
key_user_2 => "Alt-2",
key_user_3 => "Alt-3",
key_user_4 => "Alt-4",
mouse_paste => "Button-2",
auto_quit => "yes",
auto_close => 5,
@ -87,6 +98,8 @@ my %default_config = (
history_height => 10,
command => q{},
command_pre => q{},
command_post => q{},
hide_menu => 0,
max_host_menu_items => 30,
@ -96,6 +109,16 @@ my %default_config = (
macro_username => '%u',
macro_newline => '%n',
macro_version => '%v',
macro_user_1 => '%1',
macro_user_2 => '%2',
macro_user_3 => '%3',
macro_user_4 => '%4',
macro_user_1_command => '',
macro_user_2_command => '',
macro_user_3_command => '',
macro_user_4_command => '',
hostname_override => '',
max_addhost_menu_cluster_items => 6,
menu_send_autotearoff => 0,
@ -272,6 +295,15 @@ sub parse_config_file {
if ( $read_config{terminal_font} );
$self->validate_args(%read_config);
# Look at the user macros and if not set remove the hotkey for them
for my $i (qw/ 1 2 3 4 /) {
if ( !$self->{"macro_user_${i}_command"} ) {
delete $self->{"key_user_${i}"};
}
}
return $self;
}
sub load_configs {
@ -283,7 +315,7 @@ sub load_configs {
$ENV{HOME} . '/.clusterssh/config',
)
{
$self->parse_config_file($config) if ( -e $config );
$self->parse_config_file($config) if ( -e $config && !-d _ );
}
# write out default config file if necesasry
@ -298,10 +330,22 @@ sub load_configs {
# relative to config directory
for my $config (@configs) {
next unless ($config); # can be null when passed from Getopt::Long
$self->parse_config_file($config) if ( -e $config );
$self->parse_config_file($config) if ( -e $config && !-d _ );
my $file = $ENV{HOME} . '/.clusterssh/config_' . $config;
$self->parse_config_file($file) if ( -e $file );
$self->parse_config_file($file) if ( -e $file && !-d _ );
}
# Override confuration via environment variable using cssh_ prefix
# eg: terminal_size => cssh_terminal_size
foreach my $config_key ( sort( keys(%default_config) ) ) {
my $env_config_key = "cssh_" . $config_key;
if ( exists $ENV{ uc($env_config_key) } ) {
$env_config_key = uc($env_config_key);
}
if ( exists $ENV{$env_config_key} ) {
$self->{$config_key} = $ENV{$env_config_key};
}
}
return $self;
@ -526,18 +570,6 @@ sub dump {
1;
=pod
=head1 NAME
ClusterSSH::Config - Object representing application configuration
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=head1 METHODS
=over 4
@ -578,21 +610,3 @@ are loaded).
Write currently defined configuration to STDOUT
=back
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -1,15 +1,22 @@
package App::ClusterSSH::Getopt;
use strict;
use warnings;
use version;
our $VERSION = version->new('0.01');
package App::ClusterSSH::Getopt;
# ABSTRACT: App::ClusterSSH::Getopt - module to process command line args
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=cut
use Carp;
use Try::Tiny;
use Pod::Usage;
use Getopt::Long qw(:config no_ignore_case bundling no_auto_abbrev);
use Getopt::Long 2.48 qw(:config no_ignore_case bundling no_auto_abbrev);
use FindBin qw($Script);
use base qw/ App::ClusterSSH::Base /;
@ -88,7 +95,7 @@ sub add_option {
}
$desc .= " $arg" if ($arg);
$short .= " $arg" if ( $short && $arg );
$long .= " $arg" if ( $long && $arg );
$long .= " $arg" if ( $long && $arg );
}
$args{option_desc} = $desc;
$args{option_short} = $short;
@ -145,7 +152,7 @@ sub add_common_options {
$self->add_option(
spec => 'autoquit|q',
help => $self->loc(
'Toggle automatically quiting after the last client window has closed (overriding the config file).'
'Toggle automatically quitting after the last client window has closed (overriding the config file).'
),
);
$self->add_option(
@ -419,7 +426,7 @@ sub output {
sub _generate_pod {
my ($self) = @_;
output $/ , "=pod";
output $/, "=pod";
output '=head1 ', $self->loc('NAME');
output "$Script - ", $self->loc("Cluster administration tool");
output '=head1 ', $self->loc('VERSION');
@ -439,6 +446,28 @@ sub _generate_pod {
}
print $/, $/;
output '=head1 ', $self->loc('RELATED');
output $self->loc(
q{Also see the individual man pages for each of these utilities});
my %utils = (
ctel => 'telnet',
cssh => 'ssh',
crsh => 'rsh',
csftp => 'sftp',
ccon => 'console',
);
output '=over';
for my $util ( sort grep { !/$Script/ } keys %utils ) {
output "=item $util - "
. $self->loc( q{Use '[_1]' as the communication method},
$utils{$util} );
}
output '=back';
output '=head1 ', $self->loc('DESCRIPTION');
output $self->loc(
q{The command opens an administration console and an xterm to all specified hosts. Any text typed into the administration console is replicated to all windows. All windows may also be typed into directly.
@ -552,6 +581,14 @@ would replace the <Alt-n> with the client's name in each window.}
output $self->loc(q{Retile all the client windows.});
output '=item ', $self->parent->config->{key_username};
output $self->loc(q{Paste in the username for the connection});
output '=item ', $self->parent->config->{key_user_1} || 'Alt-1';
output '=item ', $self->parent->config->{key_user_2} || 'Alt-2';
output '=item ', $self->parent->config->{key_user_3} || 'Alt-3';
output '=item ', $self->parent->config->{key_user_4} || 'Alt-4';
output $self->loc(
q{Run the matching user defined macro on the server and send the output to the client}
);
output '=back';
output '=head1 ' . $self->loc('EXAMPLES');
@ -665,6 +702,18 @@ would replace the <Alt-n> with the client's name in each window.}
'Enable or disable alternative algorithm for calculating terminal positioning.',
);
output '=item command_pre =';
output '=item command_post =';
output $self->loc(
q{Add extra commands around the communication method. For example:
command_pre= . $HOME/virtualenvs/default/bin/active ;
command_post= | ct
would allow for using Python virtual envronments and then piping all shell output through C<chromaterm> for syntax highlighting. Note: you must use appropriate command separators/terminators to keep the meaning of the command pipline (such as C<;> and C<|> between commands).
These are not put through macro parsing.}
);
output '=item comms = ' . $self->parent->config->{comms};
output $self->loc(
'Sets the default communication method (initially taken from the name of the program, but can be overridden here).'
@ -687,7 +736,7 @@ Commands:
C<< open <tag|hostname> >> - open new sessions to provided tag or hostname
C<< retile >> - force window retiling
e.g.: C<< echo 'open localhost' >> /path/to/external_command_pipe >>}
);
@ -761,15 +810,64 @@ If the external command is given a C<-L> option it should output a list of tags
'L<KEY SHORTCUTS>'
);
output '=item key_user_1 = Alt-1';
output '=item key_user_2 = Alt-2';
output '=item key_user_3 = Alt-3';
output '=item key_user_4 = Alt-4';
output $self->loc(
q{Default key sequence to send user defined macros to client. If the matching [_2] macro is undefined, the sequence is passed straight to the terminal. See [_1] for more information.},
'L<KEY SHORTCUTS>',
'L<macro_user_1>'
);
output '=item macro_servername = %s';
output '=item macro_hostname = %h';
output '=item macro_username = %u';
output '=item macro_newline = %n';
output '=item macro_version = %v';
output '=item macro_user_1 = %1';
output '=item macro_user_2 = %2';
output '=item macro_user_3 = %3';
output '=item macro_user_4 = %4';
output $self->loc(
q{Change the replacement macro used when either using a 'Send' menu item, or when pasting text into the main console.}
);
output '=item macro_user_1_command =';
output '=item macro_user_2_command =';
output '=item macro_user_3_command =';
output '=item macro_user_4_command =';
output $self->loc(
q{User defined macros - the macro is run through the shell on the server and the output is sent to the client. For example,},
);
output "C<macro_user_1_command=echo echo macro_user_1>";
output $self->loc(
q{
would send the text [_1] into the terminal session.
},
'C<echo macro_user_1>'
);
output "C<macro_user_1_command=env | grep CSSH>";
output $self->loc(
q{
would send the CSSH environment variables to the client.
},
);
output $self->loc(
"The following environment variables are set in the shell of the macro process"
);
output '=over';
output '=item C<CSSH_SERVERNAME>';
output '=item C<CSSH_HOSTNAME>';
output '=item C<CSSH_USERNAME>';
output '=item C<CSSH_CONNECTION_STRING>';
output '=item C<CSSH_CONNECTION_PORT>';
output '=item C<CSSH_VERSION>';
output '=back';
output '=item macros_enabled = yes';
output $self->loc(
q{Enable or disable macro replacement. Note: this affects all the [_1] variables above.},
@ -1106,20 +1204,6 @@ See http://dev.perl.org/licenses/ for more information.
1;
__DATA__
=pod
=head1 NAME
App::ClusterSSH::Getopt - module to process command line args
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=head1 METHODS
=over 4
@ -1134,17 +1218,17 @@ Add extra options into the allowed set for parsing from the command line
=item $obj=ClusterSSH::Getopts->add_common_options ({ })
Add common options used by most calling scripts into the allowed set for
Add common options used by most calling scripts into the allowed set for
parsing from the command line
=item $obj=ClusterSSH::Getopts->add_common_session_options ({ })
Add common session options used by most calling scripts into the allowed
Add common session options used by most calling scripts into the allowed
set for parsing from the command line
=item $obj=ClusterSSH::Getopts->add_common_ssh_options ({ })
Add common ssh options used by most calling scripts into the allowed
Add common ssh options used by most calling scripts into the allowed
set for parsing from the command line
=item $obj->getopts
@ -1163,21 +1247,3 @@ Simple helper func to print out pod lines with double returns
Functions to output help and usage instructions
=back
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -1,10 +1,17 @@
package App::ClusterSSH::Helper;
use strict;
use warnings;
use version;
our $VERSION = version->new('0.02');
package App::ClusterSSH::Helper;
# ABSTRACT: ClusterSSH::Helper - Object representing helper script
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=cut
use Carp;
use Try::Tiny;
@ -45,6 +52,8 @@ sub script {
}
}
my $command_pre = $config->{command_pre} || q{};
my $command_post = $config->{command_post} || q{};
my $comms = $config->{ $config->{comms} };
my $comms_args = $config->{ $config->{comms} . '_args' };
my $config_command = $config->{command};
@ -62,9 +71,9 @@ sub script {
my \$user=shift;
my \$port=shift;
my \$mstr=shift;
my \$command="$comms $comms_args ";
my \$command="$command_pre $comms $comms_args ";
open(PIPE, ">", \$pipe) or die("Failed to open pipe: \$!\\n");
print PIPE "\$\$:\$ENV{WINDOWID}"
print PIPE "\$\$:\$ENV{WINDOWID}"
or die("Failed to write to pipe: $!\\n");
close(PIPE) or die("Failed to close pipe: $!\\n");
if(\$svr =~ m/==\$/)
@ -98,6 +107,7 @@ sub script {
if("$config_command") {
\$command .= " \\\"$config_command\\\"";
}
\$command .= "$command_post";
\$command .= " ; $postcommand";
# provide some info for debugging purposes
warn("Running: \$command\\n");
@ -120,18 +130,6 @@ sub script {
1;
=pod
=head1 NAME
ClusterSSH::Helper - Object representing helper script
=head1 SYNOPSIS
=head1 DESCRIPTION
Object representing application configuration
=head1 METHODS
=over 4
@ -145,21 +143,3 @@ Create a new helper object.
Return the helper script
=back
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -1,10 +1,25 @@
package App::ClusterSSH::Host;
use strict;
use warnings;
use version;
our $VERSION = version->new('0.03');
package App::ClusterSSH::Host;
# ABSTRACT: ClusterSSH::Host - Object representing a host.
=head1 SYNOPSIS
use ClusterSSH::Host;
my $host = ClusterSSH::Host->new({
hostname => 'hostname',
});
my $host = ClusterSSH::Host->parse_host_string('username@hostname:1234');
=head1 DESCRIPTION
Object representing a host. Include details to contact the host such as
hostname/ipaddress, username and port.
=cut
use Carp;
use Net::hostent;
@ -328,26 +343,6 @@ use overload (
1;
=pod
=head1 NAME
ClusterSSH::Host - Object representing a host.
=head1 SYNOPSIS
use ClusterSSH::Host;
my $host = ClusterSSH::Host->new({
hostname => 'hostname',
});
my $host = ClusterSSH::Host->parse_host_string('username@hostname:1234');
=head1 DESCRIPTION
Object representing a host. Include details to contact the host such as
hostname/ipaddress, username and port.
=head1 METHODS
=over 4
@ -386,7 +381,7 @@ Set specific details about the host after its been created.
=item get_realname
If the server name provided is not an IP address (either IPv4 or IPv6)
attempt to resolve it and retun the discovered names.
attempt to resolve it and return the discovered names.
=item get_givenname
@ -431,21 +426,3 @@ the IPv6 address or a port definition?) and assumes it is part of address.
Use brackets to avoid seeing warning.
=back
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -1,22 +1,9 @@
package App::ClusterSSH::L10N;
use strict;
use warnings;
use Locale::Maketext 1.01;
use base qw(Locale::Maketext);
package App::ClusterSSH::L10N;
# This projects primary language is English
our %Lexicon = ( '_AUTO' => 1, );
1;
=pod
=head1 NAME
ClusterSSH::L10N - Base translations module
# ABSTRACT: ClusterSSH::L10N - Base translations module
=head1 SYNOPSIS
@ -35,20 +22,13 @@ NOTE: the default language of this module is English.
See Locale::Maketext - there are currently no extra methods in this module.
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
use Locale::Maketext 1.01;
use base qw(Locale::Maketext);
# This projects primary language is English
our %Lexicon = ( '_AUTO' => 1, );
1;

View file

@ -1,15 +1,6 @@
package App::ClusterSSH::L10N::en;
use base 'App::ClusterSSH::L10N';
%Lexicon = ( '_AUTO' => 1, );
1;
=pod
=head1 NAME
App::ClusterSSH::L10N::en - Base English translations module
# ABSTRACT: App::ClusterSSH::L10N::en - Base English translations module
=head1 SYNOPSIS
@ -22,24 +13,14 @@ App::ClusterSSH::L10N::en - Base English translations module
L<Locale::Maketext> based translation module for ClusterSSH. See
L<Locale::Maketext> for more information and usage.
=cut
use base 'App::ClusterSSH::L10N';
%Lexicon = ( '_AUTO' => 1, );
1;
=head1 METHODS
No method are exported. See L<Locale::Maketext>.
=head1 AUTHOR
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
=head1 LICENSE AND COPYRIGHT
Copyright 1999-2016 Duncan Ferguson.
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=cut
1;

View file

@ -0,0 +1,68 @@
use strict;
use warnings;
package App::ClusterSSH::Window;
# ABSTRACT: App::ClusterSSH::Window - Base obejct for different types of window module
=head1 DESCRIPTION
Base object to allow for configuring and using different types of windows libraries
=cut
=head1 METHODS
=over 4
=cut
use Carp;
use base qw/ App::ClusterSSH::Base /;
# Module to contain window generic code and pull in specific code from
# an appropriate module
sub import {
my ($class) = @_;
# If we are building or in test here, just exit
# as the build servers will not have Tk installed
if ( $ENV{AUTHOR_TESTING} || $ENV{RELEASE_TESTING} ) {
print STDERR
"skipping initialisation; AUTHOR_TESTING or RELEASE_TESTING are set\n";
return;
}
# Find what windows module we should be using and just overlay it into
# this object
my $package_name = __PACKAGE__ . '::Tk';
( my $package_path = $package_name ) =~ s{::}{/}g;
require "$package_path.pm";
$package_name->import();
{
no strict 'refs';
push @{ __PACKAGE__ . '::ISA' }, $package_name;
}
}
my %servers;
=item $obj = App::ClusterSSH::Window->new({});
Creates object
=back
=cut
sub new {
my ( $class, %args ) = @_;
my $self = $class->SUPER::new(%args);
return $self;
}
1;

File diff suppressed because it is too large Load diff

View file

@ -109,6 +109,7 @@ like(
);
$base = undef;
my $get_config;
trap {
$base = App::ClusterSSH::Base->new( debug => 7, );
};
@ -123,9 +124,14 @@ like(
'got expected new() output'
);
trap {
$get_config = $base->config();
};
$trap->quiet("No issus with config call");
is( $get_config, undef, "config set undef as expected" );
# config tests
$base = undef;
my $get_config;
my $object;
trap {
$base = App::ClusterSSH::Base->new( debug => 3, );
@ -240,7 +246,104 @@ trap {
is( $trap->leaveby, 'die', 'died ok' );
isa_ok( $trap->die, 'App::ClusterSSH::Exception',
'Caught exception object OK' );
is( $trap->die, q{"type" arg not passed}, 'missing type arg die message' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, q{"type" arg not passed}, 'missing type arg die message' );
is( $trap->stderr, '', 'Expecting no STDERR' );
my $get_options;
$base = undef;
trap {
$base = App::ClusterSSH::Base->new( debug => 3 );
};
isa_ok( $base, 'App::ClusterSSH::Base' );
is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->stdout, '', 'Expecting no STDOUT' );
is( $base->parent, undef, 'Expecting no parent set' );
trap {
$get_options = $base->options();
};
$trap->quiet("No extra output");
is( $get_options, undef, "options call correctly unset" );
$base = undef;
trap {
$base = App::ClusterSSH::Base->new( debug => 3, parent => 'guardian' );
};
isa_ok( $base, 'App::ClusterSSH::Base' );
is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->stdout, '', 'Expecting no STDOUT' );
is( $base->parent, 'guardian', 'Expecting no STDOUT' );
trap {
$get_options = $base->options();
};
$trap->quiet("No extra output");
is( $get_options, undef, "options call correctly unset" );
$base = undef;
trap {
$base = App::ClusterSSH::Base->new(
debug => 3,
parent => { config => 'set', options => 'set' }
);
};
isa_ok( $base, 'App::ClusterSSH::Base' );
is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->stdout, '', 'Expecting no STDOUT' );
is( ref( $base->parent ), 'HASH', 'Expecting no STDOUT' );
is( $base->parent->{config}, 'set', 'Expecting no STDOUT' );
trap {
$get_options = $base->options();
};
is( ref($get_options), '', "options call correctly set" );
is( $get_options, 'set', "options call hash value correctly set" );
$trap->quiet("No extra output");
my $sort;
trap {
$sort = $base->sort;
};
$trap->quiet("No errors getting 'sort'");
# NOTE: trap doesnt like passing code refs, so recreate here
$sort = $base->sort;
is( ref($sort), 'CODE', "got results from sort" );
my @sorted = $sort->( 4, 8, 1, 5, 3 );
my @expected = ( 1, 3, 4, 5, 8 );
is_deeply( \@sorted, \@expected, "simple sort results okay" );
$base = undef;
trap {
$base = App::ClusterSSH::Base->new(
debug => 3,
parent => { config => { use_natural_sort => 1 }, options => 'set' }
);
};
isa_ok( $base, 'App::ClusterSSH::Base' );
is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->stdout, '', 'Expecting no STDOUT' );
trap {
$sort = $base->sort;
};
# May get an error here if Sort::Naturally is not installed
# $trap->quiet("No errors getting 'sort'");
is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( ref($sort), 'CODE', "got results from sort" );
@sorted = $sort->( 4, 8, 1, 5, 3 );
@expected = ( 1, 3, 4, 5, 8 );
is_deeply( \@sorted, \@expected, "simple sort results okay" );
done_testing();

View file

@ -188,7 +188,7 @@ is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, undef, 'Expecting no die message' );
is( $getopts->option1, 8, 'default value overridden' );
@ARGV = ( '--option1', '--option2', 'string', '--option3', '10' );
@ARGV = ( '--option1', '--option2', 'string', '--option3', '10' );
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
trap {
$getopts->add_option( spec => 'hidden', hidden => 1, no_acessor => 1, );
@ -287,7 +287,7 @@ is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, undef, 'Expecting no die message' );
my $pod;
@ARGV = ('--generate-pod');
@ARGV = ('--generate-pod');
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
$getopts->add_option(
spec => 'long_opt|l=s',
@ -295,7 +295,7 @@ $getopts->add_option(
default => 'default string'
);
$getopts->add_option( spec => 'another_long_opt|n=i', );
$getopts->add_option( spec => 'a=s', help => 'short option only', );
$getopts->add_option( spec => 'a=s', help => 'short option only', );
$getopts->add_option( spec => 'long', help => 'long option only', );
trap {
$getopts->getopts;
@ -309,7 +309,7 @@ $pod = $trap->stdout;
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, undef, 'Expecting no die message' );
@ARGV = ('--help');
@ARGV = ('--help');
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
trap {
$getopts->getopts;
@ -320,7 +320,7 @@ ok( defined( $trap->stdout ), 'Expecting no STDOUT' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, undef, 'Expecting no die message' );
@ARGV = ('-?');
@ARGV = ('-?');
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
trap {
$getopts->getopts;
@ -331,7 +331,7 @@ ok( defined( $trap->stdout ), 'Expecting no STDOUT' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, undef, 'Expecting no die message' );
@ARGV = ('-v');
@ARGV = ('-v');
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
trap {
$getopts->getopts;
@ -342,7 +342,7 @@ like( $trap->stdout, qr/^Version: /, 'Version string correct' );
is( $trap->stderr, '', 'Expecting no STDERR' );
is( $trap->die, undef, 'Expecting no die message' );
@ARGV = ('-@');
@ARGV = ('-@');
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
trap {
$getopts->getopts;
@ -380,8 +380,8 @@ is( $mock_object->{show_history}, 0, 'show_history set right' );
is( $mock_object->{use_all_a_records}, 1, 'use_all_a_records set right' );
@ARGV = (
'--unique-servers', '--title', 'title', '-p', '22', '--autoquit',
'--tile', '--show-history', '-A',
'--unique-servers', '--title', 'title', '-p', '22', '--autoquit',
'--tile', '--show-history', '-A',
);
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object, );
trap {
@ -425,7 +425,7 @@ TODO: {
is( $trap->die, undef, 'Expecting no die message' );
}
@ARGV = ( '--rows', 5, '--cols', 10 );
@ARGV = ( '--rows', 5, '--cols', 10 );
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object, );
trap {
$getopts->getopts;

View file

@ -754,7 +754,7 @@ is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( $trap->stdout, '', 'No unexpected STDOUT' );
isa_ok( $host, "App::ClusterSSH::Host" );
is( $host, 'ssh_test', 'stringify works' );
is( $host, 'ssh_test', 'stringify works' );
is( $host->check_ssh_hostname, 0, 'check_ssh_hostname ok for ssh_test', );
trap {
@ -767,9 +767,9 @@ is( $trap->leaveby, 'return', 'returned ok' );
is( $trap->die, undef, 'returned ok' );
is( $trap->stdout, '', 'No unexpected STDOUT' );
isa_ok( $host, "App::ClusterSSH::Host" );
is( $host, 'ssh_test', 'stringify works' );
is( $host, 'ssh_test', 'stringify works' );
is( $host->check_ssh_hostname, 0, 'check_ssh_hostname ok for ssh_test', );
is( $host->get_type, q{}, 'hostname type is correct for ssh_test', );
is( $host->get_type, q{}, 'hostname type is correct for ssh_test', );
for my $ssh_file (qw/ 10host_ssh_config 10host_ssh_include/) {
my @hosts = (

View file

@ -18,7 +18,7 @@ BEGIN {
use Test::More;
use Test::Trap;
use File::Which qw(which);
use File::Temp qw(tempdir);
use File::Temp qw(tempdir);
use Test::Differences;
use Readonly;
@ -52,6 +52,10 @@ Readonly::Hash my %default_config => {
key_macros_enable => "Alt-p",
key_paste => "Control-v",
key_username => "Alt-u",
key_user_1 => "Alt-1",
key_user_2 => "Alt-2",
key_user_3 => "Alt-3",
key_user_4 => "Alt-4",
mouse_paste => "Button-2",
auto_quit => "yes",
auto_close => 5,
@ -97,7 +101,11 @@ Readonly::Hash my %default_config => {
history_width => 40,
history_height => 10,
hostname_override => '',
command => q{},
command_pre => q{},
command_post => q{},
title => q{15CONFIG.T},
comms => q{ssh},
hide_menu => 0,
@ -109,6 +117,15 @@ Readonly::Hash my %default_config => {
macro_username => '%u',
macro_newline => '%n',
macro_version => '%v',
macro_user_1 => '%1',
macro_user_2 => '%2',
macro_user_3 => '%3',
macro_user_4 => '%4',
macro_user_1_command => '',
macro_user_2_command => '',
macro_user_3_command => '',
macro_user_4_command => '',
max_addhost_menu_cluster_items => 6,
menu_send_autotearoff => 0,
@ -188,6 +205,9 @@ $expected{screen_reserve_left} = 100;
$expected{screen_reserve_right} = 100;
$expected{screen_reserve_top} = 100;
$expected{screen_reserve_bottom} = 160;
# Note: the parse_config here removes the key_user_x entries
delete( $expected{"key_user_$_"} ) for (qw/ 1 2 3 4 /);
trap {
$config = $config->parse_config_file( $file, );
};
@ -328,6 +348,9 @@ open( my $csshrc, '>', $ENV{HOME} . '/.csshrc' );
print $csshrc 'auto_quit = no', $/;
close($csshrc);
$expected{auto_quit} = 'no';
# Note: the load_configs here removes the key_user_x entries
delete( $expected{"key_user_$_"} ) for (qw/ 1 2 3 4 /);
$config = App::ClusterSSH::Config->new();
trap {
$config->load_configs();
@ -514,7 +537,7 @@ SKIP: {
chmod( 0755, $ENV{HOME} . '/.csshrc.DISABLED', $ENV{HOME} );
}
note('check failure to write default config is caught');
note('check failure to write default config is caught when loading config');
$ENV{HOME} = tempdir( CLEANUP => 1 );
mkdir( $ENV{HOME} . '/.clusterssh' );
mkdir( $ENV{HOME} . '/.clusterssh/config' );
@ -545,6 +568,8 @@ auto_close=5
auto_quit=yes
auto_wm_decoration_offsets=no
cols=-1
command_post=
command_pre=
console=console
console_args=
console_position=
@ -557,6 +582,7 @@ fillscreen=no
hide_menu=0
history_height=10
history_width=40
hostname_override=
key_addhost=Control-Shift-plus
key_clientname=Alt-n
key_history=Alt-h
@ -565,11 +591,23 @@ key_macros_enable=Alt-p
key_paste=Control-v
key_quit=Alt-q
key_retilehosts=Alt-r
key_user_1=Alt-1
key_user_2=Alt-2
key_user_3=Alt-3
key_user_4=Alt-4
key_username=Alt-u
lang=en
macro_hostname=%h
macro_newline=%n
macro_servername=%s
macro_user_1=%1
macro_user_1_command=
macro_user_2=%2
macro_user_2_command=
macro_user_3=%3
macro_user_3_command=
macro_user_4=%4
macro_user_4_command=
macro_username=%u
macro_version=%v
macros_enabled=yes

View file

@ -16,6 +16,10 @@ key_paste=Control-v
key_quit=Control-q
key_retilehosts=Alt-r
key_username=Alt-n
key_user_1=Alt-1
key_user_2=Alt-2
key_user_3=Alt-3
key_user_4=Alt-4
max_host_menu_items=30
method=ssh
mouse_paste=Button-2

View file

@ -12,7 +12,7 @@ use lib "$Bin/../lib";
use Test::More;
use Test::Trap;
use File::Which qw(which);
use File::Temp qw(tempdir);
use File::Temp qw(tempdir);
use Readonly;
@ -81,7 +81,7 @@ trap {
is( $trap->leaveby, 'die', 'returned ok' );
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
is( $trap->stderr, q{}, 'Expecting no STDERR' );
is( $trap->die, q{Config 'method_args' not provided}, 'missing arg' );
is( $trap->die, q{Config 'method_args' not provided}, 'missing arg' );
$mock_config->{method_args} = 'rubbish';
$mock_config->{command} = 'echo';

View file

@ -84,21 +84,23 @@ isa_ok( $cluster1, 'App::ClusterSSH::Cluster' );
# no point running this test as root since root cannot be blocked
# from accessing the file
if ( $EUID != 0 ) {
my $no_read = $Bin . '/30cluster.cannot_read';
chmod 0000, $no_read;
trap {
$cluster1->read_cluster_file($no_read);
};
chmod 0644, $no_read;
isa_ok( $trap->die, 'App::ClusterSSH::Exception::LoadFile' );
is( $trap->die,
"Unable to read file $no_read: Permission denied",
'Error on reading an existing file ok'
);
}
else {
pass('Cannot test for lack of read access when run as root');
TODO: {
if ( $EUID != 0 ) {
my $no_read = $Bin . '/30cluster.cannot_read';
chmod 0000, $no_read;
trap {
$cluster1->read_cluster_file($no_read);
};
chmod 0644, $no_read;
isa_ok( $trap->die, 'App::ClusterSSH::Exception::LoadFile' );
is( $trap->die,
"Unable to read file $no_read: Permission denied",
'Error on reading an existing file ok'
);
}
else {
pass('Cannot test for lack of read access when run as root');
}
}
$expected{tag1} = ['host1'];

View file

@ -29,4 +29,24 @@ $app = App::ClusterSSH->new();
isa_ok( $app, 'App::ClusterSSH' );
isa_ok( $app->config, 'App::ClusterSSH::Config' );
for my $submod (qw/ cluster helper options window /) {
trap {
$app->$submod;
};
$trap->quiet("$submod loaded okay");
}
trap {
$app->exit_prog;
};
$trap->quiet("No errors from exit_prog call");
my @provided = (qw/ one one one two two three four four four /);
my @expected = sort (qw/ one two three four /);
my @got;
trap {
@got = sort $app->remove_repeated_servers(@provided);
};
is_deeply( \@got, \@expected, "Repeated servers removed okay" );
done_testing();

View file

@ -3,6 +3,6 @@
# small 'fake' script to allow xterm to be found when performing tests
# on systems that do not have it
warn "$_=$ENV{$_}",$/ for (sort keys %ENV) if ( $ENV{TEST_VERBOSE} );;
warn "$_=$ENV{$_}", $/ for ( sort keys %ENV ) if ( $ENV{TEST_VERBOSE} );
exit 0

View file

@ -1,4 +1,9 @@
use Test::More;
unless ( $ENV{RELEASE_TESTING} ) {
plan( skip_all => "Author tests not required for installation" );
}
eval 'use Test::CPAN::Changes';
plan skip_all => 'Test::CPAN::Changes required for this test' if $@;
changes_ok();

View file

@ -30,7 +30,7 @@ if ( $opt->{x} ) {
# '-L' means list out available tags
if ( $opt->{L} ) {
print join(' ', sort keys %tag_lookup), $/;
print join( ' ', sort keys %tag_lookup ), $/;
exit 0;
}

View file

@ -1,11 +0,0 @@
use Test::More;
# This is the common idiom for author test modules like this, but see
# the full example in examples/checkmanifest.t and, more importantly,
# Adam Kennedy's article: http://use.perl.org/~Alias/journal/38822
eval 'use Test::DistManifest';
if ($@) {
plan skip_all => 'Test::DistManifest required to test MANIFEST';
}
manifest_ok( 'MANIFEST', 'MANIFEST.SKIP' );

View file

@ -1,16 +0,0 @@
#!perl
use strict;
use warnings;
use Test::More;
use FindBin qw($Bin);
eval "use Test::PerlTidy";
plan skip_all => "Test::PerlTidy required for testing code" if $@;
# Please see t/perltidyrc for the authors normal perltidy options
run_tests(
perltidyrc => $Bin . '/perltidyrc',
exclude => [ '_build/', 'blib/', 'Makefile.PL', ]
);

View file

@ -2,18 +2,10 @@ use strict;
use warnings;
use Test::More;
# Ensure a recent version of Test::Pod::Coverage
my $min_tpc = 1.08;
eval "use Test::Pod::Coverage $min_tpc";
plan skip_all =>
"Test::Pod::Coverage $min_tpc required for testing POD coverage"
eval "use Test::Pod::Coverage 1.00";
plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage"
if $@;
# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
# but older versions don't recognize some common documentation styles
my $min_pc = 0.18;
eval "use Pod::Coverage $min_pc";
plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
if $@;
plan skip_all => "Skipping coverage tests" unless $ENV{COVERAGE};
all_pod_coverage_ok();

View file

@ -2,6 +2,9 @@
use strict;
use warnings;
use FindBin qw($Bin);
use lib "$Bin/../lib";
use Test::More;
use Test::Trap;
use Data::Dump;
@ -10,19 +13,19 @@ require_ok('App::ClusterSSH::Range')
|| BAIL_OUT('Failed to use App::ClusterSSH::Range');
my %tests = (
'a' => 'a',
'c{a,b}' => 'ca cb',
'd{a,b,c}' => 'da db dc',
'e{0}' => 'e0',
'f{0..3}' => 'f0 f1 f2 f3',
'g{0..2,4}' => 'g0 g1 g2 g4',
'h{0..2,4..6}' => 'h0 h1 h2 h4 h5 h6',
'i{0..1,a}' => 'i0 i1 ia',
'j{0..2,a,b,c}' => 'j0 j1 j2 ja jb jc',
'k{4..6,a..c}' => 'k4 k5 k6 ka kb kc',
'l{0..2,7..9,e..g}' => 'l0 l1 l2 l7 l8 l9 le lf lg',
'm{0,1}' => 'm0 m1',
'n0..2}' => 'n0..2}',
'a' => 'a',
'c{a,b}' => 'ca cb',
'd{a,b,c}' => 'da db dc',
'e{0}' => 'e0',
'f{0..3}' => 'f0 f1 f2 f3',
'g{0..2,4}' => 'g0 g1 g2 g4',
'h{0..2,4..6}' => 'h0 h1 h2 h4 h5 h6',
'i{0..1,a}' => 'i0 i1 ia',
'j{0..2,a,b,c}' => 'j0 j1 j2 ja jb jc',
'k{4..6,a..c}' => 'k4 k5 k6 ka kb kc',
'l{0..2,7..9,e..g}' => 'l0 l1 l2 l7 l8 l9 le lf lg',
'm{0,1}' => 'm0 m1',
'n0..2}' => 'n0..2}',
'host{a,b}-test{1,2}' =>
'hosta-test1 hosta-test2 hostb-test1 hostb-test2',