Perl Message::Stack example - perl

I am using Perl to try to implement an example for the Message::Stack module from CPAN.
I get the error
Can't locate object method "new" via package "Message::Stack" at stack.pl line 3.
my $stack = Message::Stack->new;
$stack->add(Message::Stack::Message->new(
msgid => 'something_happened',
level => 'error',
scope => 'login_formm',
subject => 'username',
text => 'Something happened!'
));
# Or... for those that want to type less
$stack->add({
msgid => 'something_else_happened',
level => 'error',
scope => 'login_form',
subject => 'password',
text => 'Something else happened!'
});
# ...
my $errors = $stack->for_level('error');
# Or
my $login_form_errors = $stack->for_scope('login_form');
$login_form_errors->for_subject('username');
print "Username has ".$login_form_errors->count." errors.\n";
Please let me know which object I need to load.

I am sure that what the message actually says is
Can't locate object method "new" via package "Message::Stack" (perhaps you forgot to load "Message::Stack"?) at stack.pl line 5.
So, did you forget?
And later, when you actually try to load it using
use Message::Stack
and it tells you
Can't locate Message/Stack.pm in #INC
doesn't it occur to you that it's not found because it isn't there, and needs installing?

Related

How do I ensure a Puppet exec resource always includes `set -o pipefail`?

In a particular project, I have a lot of Puppet exec resources with pipes. This seems to work just fine.
exec { 'foobar':
command => 'foo | bar',
}
However, there are occasions where foo fails. The default behavior is to report the exit code only for the last command in the pipeline. I can fix this manually.
exec { 'foobar':
command => 'set -o pipefail; foo | bar',
provider => shell,
}
But, I want to make sure this happens in all these cases automatically. I'd like to avoid manual find/replace and auditing all uses of exec.
Am I missing some useful attribute?
Is there a wrapper I can use?
Am I, unfortunately, looking at a custom resource?
Am I missing some useful attribute?
No, Exec has no attribute that would automatically prepend additional code to the command.
Is there a wrapper I can use?
I'm not confident I understand what you mean by a "wrapper", but do see below.
Am I, unfortunately, looking at a custom resource?
If you're asking whether you need to implement a native custom type, then surely not. You can undoubtedly address this problem with a (DSL-level) defined type, though you will need to adjust all your Exec declarations to be declarations of the defined type instead. This may be what you mean by a "wrapper" -- I'm fairly sure there's no existing one for your particular purpose, but it shouldn't be hard to create one:
define mymodule::exec (
command => $title,
creates => 'NOT SET',
cwd => 'NOT SET',
# ... all other regular parameters ...
) {
$real_provider = $provider ? { 'NOT SET' => 'shell', default => $provider }
if $real_provider == 'shell' {
$real_command = "set -o pipefail; $command"
} else {
warning('Non-shell command declared via mymodule::exec')
$real_command = $command
}
exec { $title:
command => $real_command,
provider => $real_provider,
creates => $creates ? { 'NOT SET' => undef, default => $creates },
cwd => $cwd ? { 'NOT SET' => undef, default => $cwd },
# ... all remaining regular parameters ...
}
}

Perl Net::Telnet::Cisco Bad named parameter

I'm trying to get some scripting finished to deploy changes en masse to about 400 Cisco devices. I've got a perl script modified from MrAudit that's using Net::Telnet::Cisco and for the life of me, I can't figure out the named parameter component.
In the documentation, they have:
$ok = $obj->cmd($string);
$ok = $obj->cmd(String => $string,
[Output => $ref,]
[Prompt => $match,]
[Timeout => $secs,]
[Cmd_remove_mode => $mode,]);
#output = $obj->cmd($string);
#output = $obj->cmd(String => $string,
[Output => $ref,]
[Prompt => $match,]
[Timeout => $secs,]
[Cmd_remove_mode => $mode,]
[Normalize_cmd => $boolean,]);
And my code is:
$testString is the test command I'm running against the device, $userTest1 is an array being cast where I want the output to be stored.
$::OPENRTR->cmd(String=>$testString,[Timeout=>5,Output=>$userTest1,]);
And every single time, no matter which component I modify or try and write it a different way, I get a variation of the error:
Odd number of elements in hash assignment at(filename)
bad named parameter "ARRAY(0x2e46460)" given to Net::Telnet::Cisco::cmd() at mrAudit-TACACSMod.pl line 279
I know it has to be something simple, but it's just flying right by. Any help would be appreciated.
I think the square brackets in the documentation just show the arguments are optional, you shouldn't use them in real code:
$OPENRTR->cmd( String => $testString,
Timeout => 5,
Output => $userTest1);

Perl CGI script print (utf-8 encoded - japanese html) over http (apache httpd) getting truncated

Environment settings
OS : RHEL 6.6 (kernel 2.6.32) - x86_64
httpd : httpd-2.2.15-39
perl : 5.10.1-136
CGI API :
perl-CGI-3.15-136
perl-CGI-Session-4.35-6
I am using a static html page with Perl-CGI defined variables in the static html. This html is read in through perl, and then passed to a perl CGI script for eval.
Note:
While reading the static html, I am using UTF-8 encoding like
open( IN ,"<:encoding(UTF-8)", $file_path )
After reading the status HTML page, the output is passed back to the CGI script through a variable and then pressed in to eval to evaluate the variables.
Finally, the eval(uated) output from CGI is print which can be read through http daemon.
In the CGI script I am using
binmode(STDIN, ':encoding(UTF-8)');
binmode(STDOUT, ':encoding(UTF-8)');
The static HTML looks something like this
When I check the output of print in the CGI script, I see the complete output as desired, like this
However on the Browser, the hidden input fields are getting truncated in an unwanted manner. Like this
When I checked the wireshark output for the text/html, which is being printed back from the server to the browser, this is also getting truncated.
Like this
The HTML header has proper Content-Type and charset declaration.
The same code is working fine with EN language
The same code is working fine with zh(chinese) language as well.
When the language is set to japanese in the browser, and we read from HTTP_ACCEPT_LANGUAGE that it is 'ja', than we print the japanese specific data.
We are not using cgid module of apache.
Are we supposed to use some special encoding for japanese language??
Or it is a double encoding issue. I have tried removing the encoding when I am reading the static html file, however, that also did not help.
The same code is working fine with RHEL 5.x (2.6.18-308), and perl-CGI-Session (4.42-2), perl (5.8.8-38) httpd (2.2.3-63), there was no perl-CGI in RHEL-5.x.
I kind of found the solution to the problem. In our code we used to add a data in the CGI::Session object, which had the language. In the following form
$session->param( KEY_SESSION_LANG, $code ).
Where $session is a CGI::Session object and KEY_SESSION_LANG is 'language' and $code is something that we get from HTTP_ACCEPT_LANGUAGE. When we see 'en' we used to set it as perl constant 'en', when we got 'ja' we used to set it as perl constant 'ja'.
When we used to form the session object we used to get a session file as (perl version RHEL 5.x (2.6.18-308) & perl-CGI-Session-4.42-2 ) for JA language we used to get the following in the cgi file
cat cgisess_e31c8d21af82b59fd064babc7ca25c01
$D = {'_SESSION_ID' => 'e31c8d21af82b59fd064babc7ca25c01','_SESSION_ETIME' => 6000,'language' => 'ja','permit' => 'yes','_SESSION_REMOTE_ADDR' => '192.168.101.1','_SESSION_CTIME' => 1441090386,'execute' => 'yes','_SESSION_ATIME' => 1441090387,'_SESSION_EXPIRE_LIST' => {}};*a = \undef;;$D
For perl CGI Session in RHEL 6.6 this is coming out to be
cat cgisess_e31c8d21af82b59fd064babc7ca25c01
$D = {'_SESSION_ID' => 'e31c8d21af82b59fd064babc7ca25c01','_SESSION_ETIME' => 6000,'language' => *a,'permit' => 'yes','_SESSION_REMOTE_ADDR' => '192.168.101.1','_SESSION_CTIME' => 1441090386,'execute' => 'yes','_SESSION_ATIME' => 1441090387,'_SESSION_EXPIRE_LIST' => {}};*a = \undef;;$D
language data for ja is becoming *a. The same is also reflected when we use perl dumper for getting in memory data.
I checked the /usr/share/perl5/vendor_perl/CGI/Session.pm and it had following information in it
=head1 A Warning about UTF8
Trying to use UTF8 in a program which uses CGI::Session has lead to problems. See RT#21981 and RT#28516.
In the first case the user tried "use encoding 'utf8';" in the program, and in the second case the user tried "$dbh->do(qq|set names 'utf8'|);".
Until this problem is understood and corrected, users are advised to avoid UTF8 in conjunction with CGI::Session.
For details, see: http://rt.cpan.org/Public/Bug/Display.html?id=28516 (and ...id=21981).
=head1 TRANSLATIONS
This document is also available in Japanese.
Now when I used the perl dumper following things happened. I quote below from my offical analysis presented on our local development portal
I think the problem is because of perl-CGI-Session OSS package, please see the analysis below.
Some inputs from the CGI session source code.
## Inputs ##
From the file /usr/share/perl5/vendor_perl/CGI/Session.pm
## Following are the status of CGI session, set internally after modification to any of the parameters ##
sub STATUS_NEW () { 1 } # denotes session that's just created
sub STATUS_MODIFIED () { 2 } # denotes session that needs synchronization
sub STATUS_DELETED () { 4 } # denotes session that needs deletion
sub STATUS_EXPIRED () { 8 } # denotes session that was expired.
--snip --
I::Session - persistent session data in CGI applications
=head1 SYNOPSIS
# Object initialization:
use CGI::Session;
$session = new CGI::Session();
$CGISESSID = $session->id();
We are setting the "language" parameter in the session object. (We create a CGI object, set cookie to it, to get sid, and through sid get the session object). For setting up the language parameter we do
$session->param( 'language', ); ---> language_value = en(english) or ja(japanese). When we have completed the printing of the HTML page in /opt/packageManager/pm_gui/cgi/status.cgi file, I checked the cgi session object it is as follows
For EN Language
Before executing session flush
[09/10/2015 16:13:41] [23722] <ERROR> status.cgi : 267 :
$VAR1 = bless( {
'_STATUS' => 2,
'_DATA' => {
'_SESSION_ETIME' => 6000,
'_SESSION_ID' => '995d11334f2c39b95b3fdb86cecd9655',
'permit' => 'yes',
'language' => 'en',
Then after this when I flush the session as $session->flush() and check the session object it is
[09/10/2015 16:13:41] [23722] <ERROR> status.cgi : 270 :
$VAR1 = bless( {
'_STATUS' => 0,
'_DATA' => {
'_SESSION_ETIME' => 6000,
'_SESSION_ID' => '995d11334f2c39b95b3fdb86cecd9655',
'permit' => 'yes',
'language' => 'en',
Inference 1: session status changed after doing flush. This is good, and should be done.
For JP Language
Before executing session flush
[09/10/2015 16:14:54] [31910] status.cgi : 267 :
$VAR1 = bless( {
'_STATUS' => 2,
'_DATA' => {
'_SESSION_ID' => '1cd1b7860af4c71264f3969fe74e7a44',
'_SESSION_ETIME' => 6000,
'language' => *a
Then after this, when I flush the session as $session->flush() and check the session object it is NOT THERE. SCRIPT CRASHES HERE IT SELF
Inference 2 : Doing flush with language JP, is terminating the session, and that is why the session gets destroyed. And that is why, ending data in response is truncated
Due to the wrong value being set in memory, in session object, and then the implicit flush by CGI session is failing on the disk. Which results in termination of the session object, and in between termination of session, and and data loss of HTML.
I checked the actual code in sessions.pm file and it seems to be coming in from here
sub param {
my ($self, #args) = #_;
--snip--
# USAGE: $s->param($name, $value);
# USAGE: $s->param($name1 => $value1, $name2 => $value2 [,...]);
# DESC: updates one or more **public** records using simple syntax
if ((#args % 2) == 0) {
my $modified_cnt = 0;
ARG_PAIR:
while (my ($name, $val) = each %args) {
if ( $name =~ m/^_SESSION_/) {
carp "param(): attempt to write to private parameter";
next ARG_PAIR;
}
$self->{_DATA}->{ $name } = $val; ----> HERE
++$modified_cnt;
}
$self->_set_status(STATUS_MODIFIED);
return $modified_cnt;
}
As a solution, we stopped putting 'ja' value as a perl constant, but now are putting it as a string "ja" and it seems to be working fine now.

What is wrong with my declaration of a hash inside a hash in Perl?

I am struggling with the following declaration of a hash in Perl:
my %xmlStructure = {
hostname => $dbHost,
username => $dbUsername,
password => $dbPassword,
dev_table => $dbTable,
octopus => {
alert_dir => $alert_dir,
broadcast_id => $broadcast_id,
system_id => $system_id,
subkey => $subkey
}
};
I've been googling, but I haven't been able to come up with a solution, and every modification I make ends up in another warning or in results that I do not want.
Perl complaints with the following text:
Reference found where even-sized list expected at ./configurator.pl line X.
I am doing it that way, since I want to use the module:
XML::Simple
In order to generate a XML file with the following structure:
<settings>
<username></username>
<password></password>
<database></database>
<hostname></hostname>
<dev_table></dev_table>
<octopus>
<alert_dir></alert_dir>
<broadcast_id></broadcast_id>
<subkey></subkey>
</octopus>
</settings>
so sometthing like:
my $data = $xmlFile->XMLout(%xmlStructure);
warn Dumper($data);
would display the latter xml sample structure.
Update:
I forgot to mention that I also tried using parenthesis instead of curly braces for the hash reference, and eventhough it seems to work, the XML file is not written properly:
I end up with the following structure:
<settings>
<dev_table>5L3IQWmNOw==</dev_table>
<hostname>gQMgO3/hvMjc</hostname>
<octopus>
<alert_dir>l</alert_dir>
<broadcast_id>l</broadcast_id>
<subkey>l</subkey>
<system_id>l</system_id>
</octopus>
<password>dZJomteHXg==</password>
<username>sjfPIQ==</username>
</settings>
Which is not exactly wrong, but I'm not sure if I'm going to have problems latter on as the XML file grows bigger. The credentials are encrypted using RC4 algorith, but I am encoding in base 64 to avoid any misbehavior with special characters.
Thanks
{} are used for hash references. To declare a hash use normal parentheses ():
my %xmlStructure = (
hostname => $dbHost,
username => $dbUsername,
password => $dbPassword,
dev_table => $dbTable,
octopus => {
alert_dir => $alert_dir,
broadcast_id => $broadcast_id,
system_id => $system_id,
subkey => $subkey
}
);
See also perldoc perldsc - Perl Data Structures Cookbook.
For your second issue, you should keep in mind that XML::Simple is indeed too simple for most applications. If you need a specific layout, you're better off with a different way of producing the XML, say, using HTML::Template. For example (I quoted variable names for illustrative purposes):
#!/usr/bin/env perl
use strict; use warnings;
use HTML::Template;
my $tmpl = HTML::Template->new(filehandle => \*DATA);
$tmpl->param(
hostname => '$dbHost',
username => '$dbUsername',
password => '$dbPassword',
dev_table => '$dbTable',
octopus => [
{
alert_dir => '$alert_dir',
broadcast_id => '$broadcast_id',
system_id => '$system_id',
subkey => '$subkey',
}
]
);
print $tmpl->output;
__DATA__
<settings>
<username><TMPL_VAR username></username>
<password><TMPL_VAR password></password>
<database><TMPL_VAR database></database>
<hostname><TMPL_VAR hostname></hostname>
<dev_table><TMPL_VAR dev_table></dev_table>
<octopus><TMPL_LOOP octopus>
<alert_dir><TMPL_VAR alert_dir></alert_dir>
<broadcast_id><TMPL_VAR broadcast_id></broadcast_id>
<subkey><TMPL_VAR subkey></subkey>
<system_id><TMPL_VAR system_id></system_id>
</TMPL_LOOP></octopus>
</settings>
Output:
<settings>
<username>$dbUsername</username>
<password>$dbPassword</password>
<database></database>
<hostname>$dbHost</hostname>
<dev_table>$dbTable</dev_table>
<octopus>
<alert_dir>$alert_dir</alert_dir>
<broadcast_id>$broadcast_id</broadcast_id>
<subkey>$subkey</subkey>
<system_id>$system_id</system_id>
</octopus>
</settings>
You're using the curly braces { ... } to construct a reference to an anonymous hash. You should either assign that to a scalar, or change the { ... } to standard parentheses ( ... ).

Why can't I call methods on my Mail::Sender object?

I have this simple part of the program that should send an email to a specified user.
But it has an error that says "Can't call method "MailMsg" on an undefined value"
if ($sender->MailMsg({smtp => 'mail.myISP.com',
from => 'suezy.ourdomainhere.com',
to =>'sample#domainhere.com',
subject => 'this is a test',
msg => "testing....\n?"}) < 0)
{
die "$Mail::Sender::Error\n";
}
print "Successfully sent."
Something wrong? Can anyone give me suggestions please?
Is it possible that I wasn't able to install the package properly?
Your problem is that $sender is not defined - i.e. the variable has no value in it.
Have you created a Sender object doing something like the following:
$sender = new Mail::Sender
{smtp => 'mail.yourdomain.com', from => 'your#address.com'};