Giter Club home page Giter Club logo

caf's People

Contributors

gombasg avatar jouvin avatar jrha avatar kwaegema avatar ned21 avatar piojo avatar piojo-zz avatar stdweird avatar ttys4 avatar wdpypere avatar wpoely86 avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

caf's Issues

upper method in tt files gives an empty string

Hi,
I'm facing this issue when I try to define a vnet with ncm-opennebula on a SL6.6 machine. Here is a code that isolates the problem :

#!/usr/bin/perl
use lib '/usr/lib/perl';
use CAF::TextRender;
my $module = 'vnet';
my %vnet = ('bridge' , 'br0', 'dns', '193.58.172.5', 'gateway', '192.168.10.200', 'name', 'Private', 'network_mask', '255.255.0.0', 'type', 'FIXED');
my $contents = \%vnet;
my $trd = CAF::TextRender->new($module, {'vnet' => $contents}, relpath => 'opennebula', log => $self);
print "$trd";

The ouput of this code is the following :

 = "br0"
 = "193.58.172.5"
 = "192.168.10.200"
 = "Private"
 = "255.255.0.0"
 = "FIXED"
QUATTOR = 1

I guess this is due to "upper" methode in vnet.tt :

[% FOR pair IN vnet.pairs -%]
[%    pair.key.upper %] = "[% pair.value %]"
[% END -%]
QUATTOR = 1

Could this be due to bug in perl-Template-Toolkit-2.22-5.el6.x86_64 ?
Cheers,
Stéphane

TextRender Config::General ordering issues on EL6

Below some debug data from TextRender with general module (a.k.a Config::General).
The service entry is a list, but the generation of the text does not keep that order on EL6.

# _store ARRAY HASH entry site line HASH(0x1221110)<site>
# _store $VAR1 = {
#           'site_location' => 'HERE',
#           'site_project' => [
#                             'MYSITE'
#                           ],
#           'address' => 'my.host.domain',
#           'site_name' => 'MYSITE',
#           'service' => [
#                        {
#                          'type' => 'bwctl'
#                        },
#                        {
#                          'type' => 'owamp'
#                        }
#                      ],
#           'is_local' => 1
#         };
# _store SCALAR entry address    address   my.host.domain
# _store SCALAR entry is_local    is_local   1
# _store ARRAY HASH entry service line HASH(0x1220df8)    <service>
# _store $VAR1 = {
#           'type' => 'owamp'
#         };
# _store SCALAR entry type        type   owamp
#     </service>
# _store ARRAY HASH entry service line HASH(0x1220e40)    <service>
# _store $VAR1 = {
#           'type' => 'bwctl'
#         };
# _store SCALAR entry type        type   bwctl
#     </service>
# _store SCALAR entry site_location    site_location   HERE
# _store SCALAR entry site_name    site_name   MYSITE
# _store ARRAY SCALAR entry site_project line MYSITE    site_project   MYSITE
# </site>

Add a rule-based file editor to CAF

In some circumstances it is required to edit some files (typically provided by a RPM) to change some configuration parameters and doing it on the template site is impractical or unmaintainable because the file provided by the RPM evolves and you just want to ensure that some critical parameters have a defined value. Doing it on the template site would require to update the templates at each new version of the RPM and would lead to a tricky dependency management between the RPM version and the template version. A typical example are EMI DPM and Xrootd, managed by ncm-dpmlfc and ncm-xrootd. Puppet for example is using the "template approach" and this is a nigthmare to express the dependency between the Puppet module version and the RPM version.

An approach that has been successfully used for many years in ncm-dpmlfc and ncm-xrootd is to use a rule-based editor in the component perl module. The basic idea is that you express the variable/keyword to be edited in your config file with some value from your Quattor configuration if some conditions are met, like a configuration option defined in a certain part of the configuration. This is very flexible and powerful. Currently, this is a (long) piece of Perl code that is inside both configuration modules (this is the same code copied/pasted, the ncm-dpmlfc being slightly more recent with a few additional features.

As this is not good to duplicate such a piece of code and because it could also be beneficial for other use cases, I'd like to add it as a new CAF module, for example FileRuleBasedEditor. Before going furtther, I'd like to discuss if there is an agreement on the features provided by the current rule-based editor.

Let start by describing how rules are constructed (see comments in https://github.com/jouvin/configuration-modules-grid/blob/dpmlfc/ncm-dpmlfc/src/main/perl/dpmlfc.pm around line 147 and the rule examples below):

  • For each file that you want to edit, you define a hash containing a set of rules.
  • For each entry in the hash (unordered), the key is matched against a "keyword" in the configuration file (the exact way of matching a keyword depends on the line format, e.g. shell script, apache config file...) and the value is defining when/how to update the configuration line. This value (a string) has the following format:
[condition->]option_name:option_set[,option_set,...];line_fmt[;value_fmt]

With:

  • condition: an option or an option set that must exist for the rule to be applied. Both option_set and option_name:option_set are accepted (see below). Only one option set is allowed and only existence, not value is tested. In addition, the condition may be negated (option or option_set must not exist) by prepending a '!' to it.
  • option_name: the name of an option that will be retrieved from the configuration
  • option_set: the set of options the option is located in (for example 'dpnsHost:dpm' means 'dpnsHost' option of 'dpm' option set (an option set is a sub-hash of the option hash passed to the rule-based editor). 'GLOBAL' is a special value for 'option_set' indicating that the option is a global option, instead of belonging to a specific option set (a global option is an option at the first level of the option hash).
  • line_fmt` indicates the line format for the parameter. The following formats are currently supported (names reflect their original usage and should be changed when moving this into CAF):
  • envvar : a sh shell environment variable definition (export VAR=val)
  • param : a sh shell variable definition (VAR=val)
  • xrdcfg : a keyword value line, as used by Xrootd or Apache config files.
  • xrdcfg_setenv : a setenv line, as used by Xrootd config files or csh/tcsh script.
  • xrdcfg_set : a set line, as used by Xrootd config files.
  • line_fmt allows to specify how to process lists and nlists. In particular if an option is a pan list, the rule-based editor can display the value of the list separated by the selected separator.
  • 'value_fmtallows special formatting of the value. This is mainly used for boolean values to get them printed asyesorno`.

Inline comments are not supported in xrdcfg family of formats whereas every line updated by Quattor receive an inline comment in envvar and paramformats.

In addition, if the keyword (hash key) is starting with a -, this means that the matching configuration line must be removed/commented out (instead of added/updated) from the configuration file if present. If it is starting with a '?', this means that the matching line must be removed/commented out if the option is undefined (note that this is also possible to specify at the file level, for the whole ruleset, if a line matching one rule but whose condition is not met must removed/commented out).

Add CAF::FileReader

Basically a FileEditor that is cancelled on construction. To make this usage pattern explicit.

CAF::Process doesn't set stdout under --noaction

When running normally stdout is at least set to an empty string, when running under --noaction it is left undef which can cause "Use of uninitialized value" errors. The handling of this difference should be handled within the API and not left as an exercise for the consumer of the API. I assume the situation with stderr will be the same.

Deal with service/daemon actions

I propose to create a new CAF::Service that implements a bunch of common methods for dealing with services / daemons/... across various OSes.

Required methods:

  • stop
  • start
  • restart: restart the daemon
  • restart via stop, sleep $interval, start
  • status : check the current state
  • reload ?

In particular we need a naming scheme (module and sub names), and a proposal how to deal with the various OSes to autodetect the appropiate module

CAF::FileStatus

Several components (see quattor/configuration-modules-grid#58 for an example) rely on LC::Check features that are not implemented in CAF::FileXxx. This is mainly:

  • LC::Check::directory: creation of a directory if it doesn't exist
  • LC::Check::status for directories: allow to define owner/group/perm... for directories
  • LC::Check::absence: remove a file/directory if it exists
  • LC::Check::symlink: symlink management

Also LC::Check::status for file can be executed through CAF::FileEditor but this is a bit of an overkill to use this interface if you just want to check/update file metadata.

It may be useful to have a CAF::FileStatus module that will act as a wrapper over LC::Check or other standard Perl module/functions (e.g. File::Path) to implement high-level features that can be tested (mocked) as other CAF modules.

Also for directory, it may be interesting to offer a directory function that combines LC::Check::directory and LC::Check::status as this is not very efficient to have to call 2 functions... This would be more consistent with CAF::FileXxx modules.

CAF::Service should allow to enable a service

It's something we discussed a while ago at the time CAF::Service was started. But it was probably an issue/PR related to something else... CAF::Service is nice as it is abstracting the details on how to start/stop a service. But we are lacking the same for configuring the permanent state of a service, abstracting chkconfig --level on EL<7 and systemctl enable on EL7.
I remember from the old discussion that Luis (and probably a few others) were opposing adding this to CAF::Service saying that it was duplicating the feature of another configuration module with the risk that you have a "conflicting" configuration. I understand the point but I still disagree as we have some configuration modules (notably dpmlfc and xrootd) where the exact list of service to permanently enable is based on the configuration processing done by the configuration module and that doing it on the template site would require to reimplement part of this logic on the template side. So I'm still advocationg that such an addition would be very useful and the doc should make clear that you have the responsibility not to manage the same service through 2 different configuration modules (chkconfig and another one).
Lacking this feature had no practical effect so far but we the release of DPM under EL7, the current ncm-dpmlfc is broken as it doesn't manage the service correctly anymore...

CAF::Metaconfig

we would like to use the templating code in other components and code, and for this purpose move large parts of ncm-metaconfig (at first glance, everything except the Configure and restart methods) to a new CAF module.

This will make CAF depend on a bunch of perl packages though.

The alternative is to use the NCM::Metaconfig methods directly (if this is possible).

CAF::FileWriter does not log file changes

Follow up from discussion in #98.

With --verbose we display the diff and log that the file was updated (which also gets echo'd to screen). Without --verbose we display nothing. Do we log anything? It would appear not because stdout is just an out of the logger, and verbose defaults to false. This seems suboptimal to me: whether a file has been changed or not should always be logged, even if not shown on stdout. Making the diff optional seems OK, especially since we don't want to log sensitive information.

A simple fix would be to log the result of the Check::File at info level. Given that until #98 this was being printed to stdout it would not be a net increase in the amount of lines shown on stdout during an interactive run.

stopping nscd fails

We regulary see ncsd restart problems when reconfiguring nodes. A sample of the output is below. After the failure nscd is not running.

Running 'service stop nscd' on the command-line returns [ OK ] and a subsequent call to ncm-ncd --co authconfig succeeds.

[INFO] running component: authconfig
---------------------------------------------------------
[INFO] authconfig command output produced:
Starting nslcd:                                            [  OK  ]
Starting nscd:                                             [  OK  ]

updated /etc/pam_ldap.conf
changed group(28) of /etc/pam_ldap.conf
Stopping nscd:                                             [FAILED]
[ERROR] Failed to restart NSCD
[INFO] configure on component authconfig executed, 1 errors, 0 warnings

Reporter: multiline messages transformed as oneliner in syslog

This issue is a follow-up for quattor/ncm-cdispd#2. CAF::Reporter logs messages to syslog by calling Sys::Syslog with the array of string. It seems that in this case syslog removes the \n that may be present at the end of each string (as in the ncm-ncd output). Do we need to do a join like in report() before passing the argument to syslog? Or do we need to do multiple calls to syslog (but the result will probably be unreadable)?

Reporter: log prefix format inconsistent

current log prefix format is a bit inconsistent. white space is inserted in e.g. [OK] to align with 4 letter prefixes such as INFO, VERB and WARN, but not with 5 letter ones like ERROR and DEBUG.

this change however affects log messages to stdout and the logfile (not to syslog), so might introduces problems with e.g. logparsers.

fix can be as simple as reverting stdweird@d1d67ea

CAF::Lock does an unlock() in its DESTROY method

During the installation of a rhel5 system, we get the following error:

[ERROR] cannot release lock file: /var/lock/quattor/ncm-ncd

This occurs a lot (at least once for every component it seems, maybe
more. Nothing goes wrong though.

Gabor tracked this down to the following:

The Sys::Syslog Perl module that comes with RH5 does not use syslog()
from libc, but tries to re-implement it. When it detects that there's
no syslog service running, it falls back to printing messages to the
console. In that mode, it does a fork() every time a message is
printed. When such a child process exists, the Perl interpreter calls
the DESTROY method of the NCM lock object, which removes the lock
file. The next time syslog() is called, or when the main process
finishes, it tries to release the lock again, but it is no longer
there, therefore the error message.

CAF::Lock doing an unlock() in its DESTROY method is conceptually
wrong, since it means applications using it and doing a fork() may
silently lose any locks they hold while thinking they still hold
it. Leaving stale lock files around if the application fails to call
unlock() explicitly would be a better failure mode.

Process: more executable subs

I propose to add to CAF (one or more) of:

  • $p->get_executable()
  • pass optional loglevel to is_executable to log the failure
  • $p->execute_if_executable() (better to find shorter name like eie 😄 ) which is basically
sub execute_if_exists 
{
    my $(self) = @_;
    if ($self->is_executable()) {
        return $self->execute();
    } else {
        $self->{log}->error("Command ".$self->get_executable()." not found or not executable");
        return 1;
    }
}

comments and voting is welcome

FileEditor: why is IO_SEEK_BEGIN/END not exported?

Even if of limited use, you can imagine use cases for using FileEditor (in order to read the content of an existing file), build a new content as an array based on the previous contents (but not throught the FileEditor methods to do complex things) and use set_contents to update the content. Under these circumstances, it would be handy to be able to use IO_SEEK_END after set_contents, as done by the standard methods. Any good reason to declare them internal constants and not to export them?

CAF::FileEditor: add a replace() variant where the newstring can reference the linere pattern

As explained in https://github.com/quattor/configuration-modules-grid/pull/86/files#diff-1ed12f02554370943ea6fe0a5944b63f, there are circumstances where you want to match lines in a file using a regexp and to modify something in the matched lines but without knowing the exact contents of the matched lines. An example is when you want to comment some lines in a configuration file that matches a certain pattern. For this you need to be able to pass variables like $1 or $+{groupname} in the newline argument and get them evaluated. I don't have the feeling that the current replace() allows this...

Add CAF::Log option to record the PID

Look at the following snippet from the ncd.log file:

2015/07/06-14:06:26 [INFO] running component: nss
2015/07/06-14:06:26 ---------------------------------------------------------
2015/07/06-14:06:35
2015/07/06-14:06:35 ------------------------------------------------------------
2015/07/06-14:06:35 [INFO] NCM-NCD version 1.4.1 started by root at: Mon Jul  6 14:06:35 2015
2015/07/06-14:06:39 [WARN] signal handler: received signal: INT
2015/07/06-14:06:39 [ERROR] ncd exiting gracefully after signal hit.
2015/07/06-14:09:52
2015/07/06-14:09:52 =========================================================
2015/07/06-14:09:52
2015/07/06-14:09:52 [OK]   0 errors, 0 warnings executing configure

With a little bit of guesswork and intuition, you can figure out what’s going on. But it would be easier to read if the PID of the ncm-ncd process was included, like this:

[1273] 2015/07/06-14:06:26 [INFO] running component: nss
[1273] 2015/07/06-14:06:26 ---------------------------------------------------------
[1280] 2015/07/06-14:06:35
[1280] 2015/07/06-14:06:35 ------------------------------------------------------------
[1280] 2015/07/06-14:06:35 [INFO] NCM-NCD version 1.4.1 started by root at: Mon Jul  6 14:06:35 2015
[1280] 2015/07/06-14:06:39 [WARN] signal handler: received signal: INT
[1280] 2015/07/06-14:06:39 [ERROR] ncd exiting gracefully after signal hit.
[1273] 2015/07/06-14:09:52
[1273] 2015/07/06-14:09:52 =========================================================
[1273] 2015/07/06-14:09:52
[1273] 2015/07/06-14:09:52 [OK]   0 errors, 0 warnings executing configure

This example occurs when the user manually launches ncm-ncd shortly after the dispatcher decides there is work to do.

Can we add an option to CAF::Log so the PID can be recorded, and then modify ncm-ncd to use that option when setting up the logger for ncd.log?

CAF::Application: open option file with CAF::FileEditor

Currently the option file seems to be open directly with an open() call. Would it be possible to open it with FileEditor instead so that we could mock the location of the option file in tests. May be handy (see ncm-cdispd add_remove_components.t test for a use case).

CAF::Download

Create new CAF::Download module to handle downloads, supporting

  • http
  • https with X509, GSS and NSS

To reuse code from / support current similar functionality from CCM and ncm-download

CAF::Service sanity check on services

systemctl commands should probably be limited to service type only (or at least assume that is the default). we could add a sanity check on the $self->{services} for each flavour, to be called after _initialize.
for linux_systemd it could be something like

sub sane_services__linux_systemd 
{
   my ($self) = @_;
   my @services;
   foreach my $service (@{$self->{services}}){
      $service .= ".service" if ($service !~ m/\.(service|target)$/);
      push (@services, $service);
   };
   $self->{services} = \@services; 
}

review the current usage of `each`

each is evil, and altough it can be used correctly, should be avoided at all costs. after learning the lesson once more (i ran into it previously, but somehow forgot), we should get rid of it.

the problem is that each sort-of remembers the last element it iterated over.
this has all sorts of nasty side effects, but the following example illustrates the danger of using each and stopping the iteration.

#!/usr/bin/perl

use strict;
use warnings;

my %h = (
    a => 1,
    b => 2,
    );

sub bad
{
    my $stop = shift;
    while (my ($k, $v) = each(%h)) {
        print "$k $v\n";
        return if $stop;
    }
}

sub good
{
    my $stop = shift;
    foreach my $k (keys%h) {
        print "$k $h{$k}\n";
        return if $stop;
    }
}


print "bad\n";
bad(1);
bad();

print "good\n";
good(1);
good();

which gives output

bad
b 2
a 1
good
b 2
b 2
a 1

FileEditor add after newline

we ran into a bug in the ncm-named component where CAF::FileEditor does a add_or_replace to the end of the file, but the file itself didn't end in a newline. (it broke resolv.conf, making the machine useless).

i plan to add support to check that add happens after a newline (if no newline is found, add/insert one), but i would like to make it default (but if you really know what you are doing, youn can disable this).

is there any objection against this? (besides being backward in-compatible)?

debug should imply verbose

As currently implemented (since the origin!), debug and verbose are completely independant. IMO, this is a non optimal behaviour as some components display a lot of useful information for debugging with verbose() and when you use --debug you don't see it.
I'd like to propose a change where setting any debug level would also set verbose. This would not implact the behaviour with --verbose only and probably make the life of developers (who are using --debug) easier.

textrender.t failing to load YAML::XS on SL6

On SL6, when trying to run mvn test on CAF master, I get the following error:

#   Failed test 'YAML::XS loaded'
#   at src/test/perl/textrender.t line 345.
Can't return outside a subroutine at /exp/si/jouvin/GitRepositories/Quattor/CAF/target/lib/perl/CAF/TextRender.pm line 417.
# Tests were run but no plan was declared and done_testing() was not seen.
src/test/perl/textrender.t ......................... 
Dubious, test returned 2 (wstat 512, 0x200)
Failed 1/55 subtests 

I guess this is because I have a missing package. But I cannot guess which one... BTW, is this package described as a CAF dependency?

CAF::FileWriter /sbin/restorecon error on Solaris

It seems I can’t use CAF::FileWriter on Solaris without getting:

(proc): exec(/sbin/restorecon, <filename>): No such file or directory

The problem is this line:

 $cmd = CAF::Process->new (['/sbin/restorecon', *$self->{filename}],
                                     log => *$self->{LOG});

It’s a harmless error but nonetheless ought to be fixed.

I suggest this is improved to test for the presence of the executable before attempting to execute it.

perl-CAF dependencies in 14.4.0-rc* and 14.5.0-rc*

Hi,

I canot install 14.4.0-rc1 perl-CAF in an sl6 system the error I get is:

2014/05/02-16:28:52 [ERROR] Failed synchronisation with upstream: Error: Package: perl-CAF-14.4.0-rc1_1.noarch (quattor-14.4.0-rc1)
Requires: perl(List::MoreUtils) >= 0.33
Available: perl-List-MoreUtils-0.22-10.el6.x86_64 (sl640_x86_64)
perl(List::MoreUtils) = 0.22
Available: perl-List-MoreUtils-0.25.2-1.el6.rft.x86_64 (rpmforge-el6-x86_64)
perl(List::MoreUtils) = 0.25
Available: perl-List-MoreUtils-0.25.2-1.el6.test.x86_64 (rpmforge-el6-x86_64)
perl(List::MoreUtils) = 0.25

0.33 rpms are around for el5 but not for el6

Master does not build on perl v5.20.3

running test test-caffileeditor_add_or_replace.t fails on v5.20.3 :

Modification of a read-only value attempted at /usr/share/perl5/vendor_perl/IO/String.pm line 345, line 16.
at /usr/share/perl5/vendor_perl/IO/String.pm line 345, line 16.
IO::String::write(CAF::FileEditor=GLOB(0x2401b60), "tsjoelala\x{a}") called at /usr/share/perl5/vendor_perl/IO/String.pm line 137
IO::String::print(CAF::FileEditor=GLOB(0x2401b60), "tsjoelala\x{a}") called at /home/kwaegema/gitrepos/extra/CAF/target/lib/perl/CAF/FileEditor.pm line 314
CAF::FileEditor::add_or_replace_lines(CAF::FileEditor=GLOB(0x2401b60), qr(xxx), qr(yyy), "tsjoelala\x{a}", 0, 51) called at src/test/perl/test-caffileeditor_add_or_replace.t line 118

CAF::FileWriter::close() always returns undef when in NoAction mode

With LC::Check::file I can find out whether a file would be modified and therefore predict the consequences - see this code in 06f2f4f:

my $result = LC::Check::file("/etc/nsswitch.conf", ... );
   if ($result) {
       # execute something with CAF::Process
   }

In NoAction mode, $result is true iff the file would be changed. I cannot find a way to reproduce this with CAF::FileWriter.

perl-CAF update should trig a ncm-cdispd restart

During deployment of 15.4.0-rc1 (quattor/release#85), I was (again) in a situation where It basically works but ncm-ncd fails during the update itself. Below are the last lines from ncm-cdispd corresponding to the upgrade:

2015/05/07-17:34:04 [WARN] ncm-ncd finished with status: 255 (ec 65280, some configuration modules failed to run successfully)
2015/05/07-17:34:46 [WARN] Component ccm failed with message: cannot execute configure on component ccm
2015/05/07-17:34:46 [WARN] Component network failed with message: cannot execute configure on component network
2015/05/07-17:34:46 [WARN] ncm-ncd finished with status: 255 (ec 65280, some configuration modules failed to run successfully)
2015/05/07-17:34:46 [INFO] Processing delayed signal TERM
2015/05/07-17:34:46 [WARN] signal handler: signal TERM received
2015/05/07-17:34:46 [WARN] terminating ncm-cdispd...

Doing aonther deploy or restarting ncm-cdispd, the next run is ok:

2015/05/07-17:45:04 [INFO] new profile arrived, examining...
updated /var/lib/ccm/profile.414/ccm-active-profile.414-2520
2015/05/07-17:45:04 [INFO] new profile identical but re-running ncm-ncd since last execution reported errors
2015/05/07-17:45:04 [INFO] about to run: /usr/sbin/ncm-ncd --configure profile grub network ccm vomsclient hostsaccess sysconfig altlogrotate aiiserver named modprobe dirperm spma dpmlfc cdp ldconf accounts filecopy xrootd mkgridmap iptables gip2 mysql cron etcservices nrpe chkconfig gridmapdir ntpd useraccess sudo lcgbdii --state /var/run/quattor-components
2015/05/07-17:45:43 [INFO] ncm-ncd finished with status: 0 (ec 0, all configuration modules ran successfully)

This is not a blocking issue as the next deployment after the update completes successfully. But I think that this happens when perl-CAF is updated if ncm-cdispd is not restarted because ncm-ncd tries to use a CAF version removed since it has started and this is causing some side effects. I'd suggest adding a post install script restarting ncm-cdispd as part of the perl-CAF upgrade.

CAF::Service options code not in sync with pod

eg for timeout one can set the timeout via the initialisation as suggested by the pod, but the code does $self->{timeout} as opposed to $self->{options}->{timeout}. Same for some other options.

Also the timeout conditional seem odd. push(@cmd, "-T", $self->{timeout}) if $self->{timeout}; with timeout 0 doesn't set the timeout to 0 (dunno if that is the default or not).

no longer import functions from CAF modules

One of the current PRs (probably the cleanup in CAF::Object in #126)
causes the following to fail

PERL5LIB=/usr/lib/perl/ perl -e 'use CAF::Process qw(execute)'
"execute" is not exported by the CAF::Process module
Can't continue after import errors at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

The question is: is this supposed to work/ required?
it is backwards incompatible, but methods should be used directly anyway.

(The other question: why was this working before, or how did the changes break this)

CAF::Process: add a getCommand() and method

It would be handy to have a getCommand() method that returns the contents of the array containing the command and its options as an array or a string, depending of the calling context. The string version would be build by joining all elements with space. The idea is to avoid having to build a temporary array with the command and its args if you want to be able for example to print them before execution. We could also add a getCmdVerb or something like this that would return the first element of the command array.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.