I am trying to install postgresql, set up a database and a user, but I am stuck at the setting up a database and use part. What I have so far is:
# Install postgres
class postgres::install {
package { [
'postgresql',
'postgresql-contrib',
]:
ensure => "installed",
}
}
But now how do I use this to create a user, database and grant all permissions on that database to that user?
You can do this a couple of ways, but the easiest way to do it repeatedly is with a define that calls a couple of execs:
Exec {
path => [
'/usr/local/sbin',
'/usr/local/bin',
'/usr/bin',
'/usr/sbin',
'/bin',
'/sbin',
]
}
define postgres::db_setup (
$dbname,
){
exec { "configure_db_${dbname}":
command => "pg command here using ${dbname}; touch success.txt"
creates => "db_${dbname}_success.txt"
}
}
define postgres::user_setup (
$dbuser,
$dbpassword,
$dbname,
){
exec { "configure_user_${dbuser}_on_${dbname}":
command => "pg command here using ${dbuser} on ${dbname} identified by ${dbpassword}; touch usersuccess.txt"
creates => "user_${dbuser}_success.txt"
}
Then when you call the defines:
postgres::db_setup { 'this_new_db':
dbname => 'mynewdbname'
}
postgres::db_user { 'this_new_db_user_on_dbname':
dbuser => 'mynewdbuser',
dbpassword => 'blahblah',
dbname => 'mynewdbname',
require => Postgres::Db_setup['this_new_db'],
}
This is a very dirty way to accomplish what you want by using dummy files to register when an exec has been completed. In my MySQL environment I use execs on scripts created with erb templates to allow more refined error checking.
Related
I'm writing a Puppet module to enforce a configuration and restart the service if needed. I'd like to do something like that:
class app_cfg {
$app_files = ['file1', 'file2', 'file3']
$app_files.each |String $file| {
exec {"sed -i 's/bar/foo/g' $file":
path => ['/bin'],
onlyif => 'grep "bar" $file 2>/dev/null',
cwd => '/opt/app/config/',
}
} ~>
service { 'app':
ensure => running,
enable => true,
}
}
I could add "notify" inside the exec but I don't want to restart my service for each file, and it looks like the notify chaining arrow doesn't work after an each loop. Do you guys have any idea how to make it work?
Thanks a lot :)
I found a workaround by inserting a for loop inside the exec resource instead of using each:
class app_cfg {
service { 'app':
ensure => running,
enable => true,
}
exec {"for file in file1 file2 file3; do sed -i 's/bar/foo/g' \$file; done":
path => ['/bin'],
onlyif => 'grep "bar" $file 2>/dev/null',
cwd => '/opt/app/config/',
provider => shell,
notify => Service['app']
}
}
I'm still pretty curious about the first solution! Did you ever manage to do something like that?
Thanks!
I could add "notify" inside the exec but I don't want to restart my
service for each file, and it looks like the notify chaining arrow
doesn't work after an each loop.
It is important to understand that the code in a Puppet manifest describes only how to build a catalog that in turn describes the desired configuration of your server. The catalog lists the classes and resources declared, their parameters and properties, and the relationships among them. The logic within a manifest does not map to actions performed when applying the resulting catalog; it is reflected only in which classes and resources are catalogued, and what their parameters, properties, and relationships are.
Thus, when you use one of the chaining arrows in a manifest, you are instructing the catalog builder to record a relationship between the two resources in the catalog, not an explicit instruction to apply or refresh a resource. No declared resource will be applied at more than once or refreshed more times than it is applied. It will be perfectly fine, therefore, to put an appropriate chain expression inside your loop, but what you cannot do is put the Service declaration itself inside the loop, because that would produce multiple declarations of it. So you might do any of these:
Declare the service (once), and use a resource reference to it in your chain expression inside the loop:
class app_cfg {
service { 'app':
ensure => running,
enable => true,
}
['file1', 'file2', 'file3'].each |String $file| {
exec {"sed -i 's/bar/foo/g' $file":
path => ['/bin'],
onlyif => 'grep "bar" $file 2>/dev/null',
cwd => '/opt/app/config/',
} ~> Service['App']
}
}
As above, but use the appropriate resource metaparameter instead of a chain expression:
class app_cfg {
service { 'app':
ensure => running,
enable => true,
}
['file1', 'file2', 'file3'].each |String $file| {
exec {"sed -i 's/bar/foo/g' $file":
path => ['/bin'],
onlyif => 'grep "bar" $file 2>/dev/null',
cwd => '/opt/app/config/',
notify => Service['app'],
}
}
}
Or declare the relationships with the help of a collector:
class app_cfg {
['file1', 'file2', 'file3'].each |String $file| {
exec {"sed -i 's/bar/foo/g' $file":
path => ['/bin'],
onlyif => 'grep "bar" $file 2>/dev/null',
cwd => '/opt/app/config/',
tag => 'app_notifier',
}
}
Exec<|tag == 'app_notifier|>
~> service { 'app':
ensure => running,
enable => true,
}
}
I use DBIx::Class::Migration
I extract data from database with command:
${MIGRATION_CMD} --schema_class ${APP_NAMESPACE} --database ${DB_TYPE} -Ilib dump_all_sets
The database is utf8 aware, but dumped fixtures has '?????' in place of utf8 character:
$HASH1 = {
id => 125,
last_name => '?????',
};
The module does not document how to tell dbic-migration script about utf8 database aware.
Is there a way to provide mysql_enable_utf8 => 1 option for dbic-migration script? Like I do that with connect:
App::Schema->connect( $DSN, $user, $password, {
mysql_enable_utf8 => 1
});
Seems I found. The section where described how DSN is parsed shows:
DBI->parse_dsn("dbi:MyDriver(RaiseError=>1):db=test;port=42")
Thus in my case I just setup DBIC_MIGRATION_DSN:
DBIC_MIGRATION_DSN='dbi:mysql(mysql_enable_utf8=>1):dbname=mydb;host=127.0.0.1;port=3306' dbic-migration ....
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 ...
}
}
As a newbie to Perl I'm struggling to find a simple way to do this. I've created a very simple table in my database:
CREATE TABLE users (
id SERIAL NOT NULL PRIMARY KEY,
username TEXT NOT NULL,
password TEXT NOT NULL);
So far I used a simple login system that has a hard coded username and password that I found online:
package Example;
use Dancer ':syntax';
our $VERSION = '0.1';
set session => "Simple";
get '/' => sub {
# template 'index',{},{layout => 0};
template 'index';
};
before sub {
if (! session('user') && request->path_info !~ m{^/login}) {
var requested_path => request->path_info;
request->path_info('/login');
}
};
get '/login' => sub {
# Display a login page; the original URL they requested is available as
# vars->{requested_path}, so could be put in a hidden field in the form
template 'login', { path => vars->{requested_path} }, {layout => 0};
};
post '/login' => sub {
# Validate the username and password they supplied
if (params->{user} eq 'user' && params->{pass} eq 'letmein') {
session user => params->{user};
redirect params->{path} || '/';
} else {
redirect printf 'login failed';
}
};
get '/logout' => sub {
session->destroy;
redirect '/';
};
How do I get started with linking the database and then matching what the user inputs with what's in the database? And also when do I implement the hashing of the passwords? Any tutorials will be greatly appreciated - I've been using metacpan but it's not providing as much detail as I need!
Dancer::Plugin::Auth::Extensible takes care of a lot of boilerplate code for you. You can get a simple login system up and running without having to write any of your own /login routes as follows.
Configure Dancer::Plugin::Auth::Extensible
Install Dancer::Plugin::Database and Dancer::Plugin::Auth::Extensible::Provider::Database and add this to config.yml:
session: "YAML"
plugins:
Auth::Extensible:
realms:
users:
provider: 'Database'
disable_roles: 1
Configure database connection
Configure your database connection in environments/development.yml so that you can have different configurations for dev and production. This is what the configuration looks like for MySQL, with the connection credentials (database name, host, username, and password) stored in a separate options file database.cfg:
plugins:
Database:
dsn: 'dbi:mysql:;mysql_read_default_file=/path/to/database.cfg'
dbi_params:
RaiseError: 1
AutoCommit: 1
For Postgres, you should use a .pgpass file to store your connection credentials. Make sure the file is not world readable. See this Stack Overflow post for an example. Test that your credentials file works on the command line and that your webserver can read it.
Your existing table appears to conform to the suggested schema in the docs, but even if it doesn't, you can adjust the table and column names in the configuration.
Lock down your routes
Add the require_login keyword to a route you want to protect. A /login route will be generated automatically with a basic login form, although you can create your own if you like.
lib/MyApp.pm
package MyApp;
use Dancer ':syntax';
use Dancer::Plugin::Auth::Extensible;
our $VERSION = '0.1';
get '/' => require_login sub {
template 'index';
};
true;
(Yes, that really is all the code you have to write. I told you it takes care of a lot of boilerplate.)
Crypt::SaltedHash is used to hash passwords automatically. Note that you should never store plaintext passwords in your database; when you add a user to your database, you should generate a hash of the password and store the hash.
Note that roles are disabled in this example. If you enable roles, you can do other nifty things like only allow users with the admin role to view admin pages.
The simplest way:
Dancer::Plugin::Authorize::Credentials::PostgreSQL
Here is a good write up how to do it properly: http://perlmaven.com/storing-passwords-in-a-an-easy-but-secure-way
post '/login' => sub {
# Validate the username and password they supplied
if (!params->{user} or !params->{pass}){
redirect printf 'login failed';
}
# use your own encryption
my $auth = auth($login, encrypt($password));
# login successful
if ($auth) {
session user => params->{user};
redirect params->{path} || '/';
} else {
redirect printf 'login failed';
}
};
Regards,
Andras
I am trying to understand Puppet parameterized classes. I have a parameterized class defined this way:
class defaults(
$no_samba = 'FALSE'
)
{
if ($no_samba =~ /TRUE/) {
notify { "will not install samba": } ;
} else {
# install samba here
}
# More server install tasks here...
}
Furthermore, I define a basenode as follows:
node basenode
{
class {'defaults':
no_samba => 'FALSE',
}
}
and then I instantiate a server:
node myserver1 inherits basenode {
Class['defaults'] { no_samba => 'TRUE' }
}
However, this does not work. The myserver1 node does not show the notify message indicating that samba will not be installed.
Here's my non-typo answer - I think you're running into http://projects.puppetlabs.com/issues/7890
Here's a code sample where I tweaked your code to get the effect you're looking for, based on the rewritten example in the ticket:
class defaults(
$no_samba = 'FALSE'
)
{
notify {"no_samba_hack" :
message => "$no_samba";
}
if ($no_samba =~ /TRUE/) {
notify { "will not install samba": }
} else {
# install samba here
}
# More server install tasks here...
}
class basenode($no_samba="FALSE") {
class {defaults: no_samba => $no_samba}
}
node yourserver {
class { 'basenode' : no_samba => 'TRUE'}
}
When I run that with 'puppet apply sample.pp' with puppet 2.7.11 on Ubuntu 12.04, I get the following output:
notice: will not install samba
notice: /Stage[main]/Defaults/Notify[will not install samba]/message: defined 'message' as 'will not install samba'
notice: TRUE
notice: /Stage[main]/Defaults/Notify[no_samba_hack]/message: defined 'message' as 'TRUE'
notice: Finished catalog run in 0.05 seconds
Was samba installed on myserver1, and/or did any of the other server install tasks get triggered ? If only the notify message wasn't printed, then it may really be a problem with notify type versus the notice function.
Notify should look like "notify{"i have curly brackets and a trailing colon":}
Notice is called like a function: notice("i use parenthesis")
Try changing 'notify' to 'notice' and see if it works. You may also want to check the puppet syntax with 'puppet parser validate default.pp' (assuming your default class is in default.pp)
I believe it has to do with scope. It looks like you're creating the 'default' class in the base node and then setting a resource default for the 'default' class after the fact in something that inherits that basenode.
http://docs.puppetlabs.com/guides/language_guide.html
"Defaults are not global — they only affect the current scope and scopes below the current one."
Here is simple example:
class apache-setup {
class { 'apache':
mpm_module => 'prefork',
}
}
include apache-setup
Or:
class { '::mysql::server':
config_file => '/etc/my.cnf',
root_password => 'root', # Sets MySQL root password.
override_options => {
'mysqld' => {
'max_connections' => '512',
'max_allowed_packet' => '256M',
'log' => 'ON',
'log_slow_queries' => 'ON',
'general_log' => 'ON',
'wait_timeout' => '28800',
}
}
}