I'm trying to use the CouchDB::Client API for Perl. I want to access a database on some server that hosts couchdb. To access local databases with no access controls this is simple:
my $client = CouchDB::Client->new('localhost', '5984');
my $conn = $client->testConnection;
print "client: $client \n";
print "connx : $conn \n";
But how does one do this for a remote host with access controls? I don't see any option for a password in the CouchDB::Client file .... I need to use Perl for this rather than any other language, maybe there's another API that is more suited that I haven't come across?
Cheers!
By default, you can include username and password into the http url like :-
CouchDB::Client->new(uri=>'http://YOUR_USERNAME:YOUR_PASSWORD#localhost:5984/');
You can do a simple test with curl :-
curl -X HEAD http://USER:PASS#localhost/_active_tasks
// required authentication
Related
I am developing a Mojolcious standalone application. In the code I am contacting an internal backend where the user should provide some credentials.
Currently I am using the credentials inside the code as variables. It looks some something like:
$password = 'somthing';
I tried to use the config plugin to store the credentials there, but is there an option with Mojolicious to let the user provide his credentials when running the daemon? Maybe like:
perl myapp.pl daemon -user username -password password
What is the best strategy with Mojolicious to handle this use case?
I will provide two solutions to this problem. One is rather easy while the other one uses a few advanced techniques.
Easy: use environment variables
You can simply pass environment variables to your app when you start it.
$ USERNAME=foo PASSWORD=bar perl app.pl daemon
Mojolicious is Perl, so they end up in %ENV. We can access them with $ENV{USERNAME} and $ENV{PASSWORD}. Typically those environment variables are all-caps. It would make sense to pick something app-specific, so MYAPP_USERNAME is probably a better choice than USERNAME.
The good thing about this is that you can also set it in your shell environment and then you never have to worry about it.
package MyApp;
use Mojolicious::Lite;
use Data::Printer;
helper(
credentials => sub {
state $credentials = {
username => $ENV{USERNAME},
password => $ENV{PASSWORD},
}
}
);
get '/' => sub {
my $c = shift;
$c->render( text => np $c->app->credentials );
};
app->start;
In the above example I have created a helper that keeps the credentials for us so it's easy to access them. Of course you could just use $ENV{USERNAME} throughout the code, but I believe it's nicer to have it properly encapsulated.
If we curl localhost:3000 the daemon we get the this output.
$ curl localhost:3000
\ {
password "bar",
username "foo"
}
Advanced: subclass the daemon Command
Command line arguments all handled by Mojolicious::Command.
You can create your own Mojolicious::Command subclass. This is documented in the Mojolicious::Cookbook. If you name it Mojolicious::Command::foo then you don't even need to worry about adding another namespace for Mojo to look for commands in.
But you can unfortunately not pass several commands at the same time. So creating a subclass credentials and then doing this does not work.
$ perl myapp.pl daemon credentials --username foo --password bar
So we need to do something else. A quick look at the Mojolicious::Command::daemon tells us that it only has the run method, which gets called automatically when that command is called. We want it to do something additional, so we subclass that specific command.
package Mojolicious::Command::mydaemon;
use Mojo::Base 'Mojolicious::Command::daemon';
use Mojo::Util 'getopt';
sub run {
my ( $self, #args ) = #_;
getopt
'u|username=s' => \my $username,
'p|password=s' => \my $password;
$self->app->credentials->{username} = $username;
$self->app->credentials->{password} = $password;
return $self->SUPER::run;
}
We need to import getopt, which helps us read stuff from the command line. We store the username and password in the credentials helper just like in the first approach because encapsulation is nice.
Finally, we need to hand over to the original run method. That's done by calling $self->SUPER::run, which is Perl's way of saying call run on my super-class from which I have inherited. It calls run on the SUPER:: pseudo class. You can learn more about that in perlobj.
Now the actual app is pretty much the same.
package MyApp;
use Mojolicious::Lite;
use Data::Printer;
helper(
credentials => sub {
state $credentials = { username => q{}, password => q{}, };
}
);
get '/' => sub {
my $c = shift;
$c->render( text => np $c->app->credentials );
};
app->start;
We run it like this:
$ perl code/scratch.pl mydaemon --username foo --password bar
And if we curl localhost:3000 we get the same output.
$ curl localhost:3000
\ {
password "bar",
username "foo"
}
Which of those ways you choose is up to you. I am not sure which one I would prefer myself. Both have merits.
The environment variables are easier to implement and more portable, but the code is not as clear. The command subclass can document itself when done properly, but maybe your users would not expect something else than daemon. It's also a lot more code.
I'm new to perl.I was trying to login to a cisco router to execute few commands.
I was able to login using Net::SSH::Perl and execute a couple of commands.
But when i tried to switch to the configure mode the script fails.
br-waas#
br-waas#configure
br-waas(config)#
Is there a perl cpan module to do this?
use Net::SSH::Perl;
my $host = "XX.XX.XX.XX";
my $user = "XXXX";
my $password = "XXXX";
my $ssh = Net::SSH::Perl->new($host);
$ssh->login($user, $password);
print "check the version of the build \n";
my ($stdout) = $ssh->cmd("show statistics accelerator http object-cache");
print $stdout;
sleep(3);
print "enter the config mode \n";
my($stdout1) = $ssh->cmd("config");
print "$stdout1 \n";
When the configure command executes the script fails with the following error. % Invalid input detected at '^' marker.
If you're having trouble with Net:SSH, Net::OpenSSH has always done the job well for me.
If you have an enable password, at the end of the day, you're going to need something implementing Expect, which is always a hassle.
The one library that worked for me is NET::Appliance::Session.
It is reliable, solves the "channel locking" issue en cisco routers/switches and can send commands without the use of expect (or at least does it internally can't remember well)
Does the command "config" work when doing this by hand? I assume you will get a question echoed back on the terminal.
If this is a plain Cisco router running IOS, the command to enter config mode is "configure terminal".
I using curl to pull a hostname from a server using a HTTP get request, and that is working fine. I need my script to modify the /etc/sysconfig/network file so I don't have to restart the system to apply the hostname.
Here is my code thus far:
#!/usr/local/bin/perl
use strict;
use warnings;
use Sys::Hostname;
my $curl = `curl http://100.10.10.10/hostname`; # Get correct hostname
my $host = hostname;
if ($curl ne $host) {
# Need to modify the /etc/sysconfig/network file to replace hostname or add it.
}
EDIT:
My Actual Question: What is the best way for me to modify that file with the new hostname?
I guess you want is
my $host = qx{hostname};
instead of
my $host = hostname;
also, why dont you just make the changes manually (i.e, open /etc/hosts or whatever file you want to edit, and edit, just make sure the $> is 0... script is running as user root).
I want to write a perl script which will read a file on a remote server, alter some parameters inside the file and get whole file data or specific data as a return value.
Actually what I was thinking is to use cpan openssh utility to create a ssh connection, then call the script on the server side, which does all the reading and changing the parameters value. But the problem in this approach is that I will get only success or failure as a return value - not the file data.
Can anyone please tell me how I will achieve this functionality?
Thanks in advance....
Here is one way to do what you are asking with Net::SSH::Expect
use Net::SSH::Expect;
my $ssh = Net::SSH::Expect->new (
host => "some.example.net",
password=> 'your-password',
user => 'you',
raw_pty => 1
);
my $login_output = $ssh->login();
if ($login_output !~ /Welcome/) {
die "Login has failed. Login output was $login_output";
}
$ssh->exec("perl -i -pe 'tr/9/a/;' temp.txt");
my $cat=$ssh->exec("cat temp.txt");
print($cat);
The file on the remote server (temp.txt) contains just one line 0123456789
and running the script has this output
$ perl /tmp/a.pl
012345678a
The main point here is that with this module I can log in to a remote machine and execute commands as I would with any other ssh session.
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new('$host',22);
$ssh->login('$user','$pass');
my $out = $ssh->cmd("show clock");
print $out;
I have the above script to have an ssh session using perl but I'm having the error message
"Can't map service name 'ssh' to port number". I'm using Windows OS. Please advise me where I'm wrong.
Try adding ssh to your services file. The services file is located at:
%SystemRoot%\system32\drivers\etc\services
The line that you'll want to add will look like:
ssh 22/tcp # Secure Shell Login