diff options
Diffstat (limited to 'lib/Config/HAProxy.pm')
-rw-r--r-- | lib/Config/HAProxy.pm | 125 |
1 files changed, 117 insertions, 8 deletions
diff --git a/lib/Config/HAProxy.pm b/lib/Config/HAProxy.pm index 9a8d666..ff4fa8a 100644 --- a/lib/Config/HAProxy.pm +++ b/lib/Config/HAProxy.pm @@ -14,2 +14,4 @@ use File::Temp qw(tempfile); use File::stat; +use File::Spec; +use IPC::Cmd; use Carp; @@ -28,3 +30,4 @@ sub new { my $filename = shift // '/etc/haproxy/haproxy.cfg'; - my $self = bless { _filename => $filename }, $class; + my $self = bless { _filename => $filename, + _lint => { enable => 1 } }, $class; $self->reset(); @@ -171,5 +174,55 @@ sub write { -sub save { +sub lint { my $self = shift; + if (@_) { + if (@_ == 1) { + $self->{_lint}{enable} = !!shift; + } elsif (@_ % 2 == 0) { + local %_ = @_; + my $v; + if (defined($v = delete $_{enable})) { + $self->{_lint}{enable} = $v; + } + if (defined($v = delete $_{command})) { + $self->{_lint}{command} = $v; + } + if (defined($v = delete $_{path})) { + $self->{_lint}{path} = $v; + } + croak "unrecognized keywords" if keys %_; + } else { + croak "bad number of arguments"; + } + } + + if ($self->{_lint}{enable}) { + $self->{_lint}{command} ||= 'haproxy -c -f'; + if ($self->{_lint}{path}) { + my ($prog, $args) = split /\s+/, $self->{_lint}{command}, 2; + if (!File::Spec->file_name_is_absolute($prog)) { + foreach my $dir (split /:/, $self->{_lint}{path}) { + my $name = File::Spec->catfile($dir, $prog); + if (-x $name) { + $prog = $name; + last; + } + } + if ($args) { + $prog .= ' '.$args; + } + $self->{_lint}{command} = $prog; + } + } + return $self->{_lint}{command}; + } +} + +sub save { + my $self = shift; + croak "bad number of arguments" if @_ % 2; + local %_ = @_; + my $dry_run = delete $_{dry_run}; + my @wrargs = %_; + return unless $self->tree;# FIXME @@ -178,4 +231,13 @@ sub save { DIR => dirname($self->filename)); - $self->write($fh, @_); + $self->write($fh, @wrargs); close($fh); + + if (my $cmd = $self->lint) { + my ($ok, $err, undef, undef, $errbuf) = + IPC::Cmd->run(command => "$cmd $tempfile"); + unless ($ok) { + croak "Syntax check failed: $errbuf\n"; + } + } + return 1 if $dry_run; @@ -190,3 +252,4 @@ sub save { - $self->tree->clear_dirty + $self->tree->clear_dirty; + return 1; } @@ -235,5 +298,8 @@ Config::HAProxy - Parser for HAProxy configuration file - $cfg->save; + $cfg->lint(enable => 1, command => 'haproxy -c -f', + path => '/sbin:/usr/sbin') + + $cfg->save(%hash); - $cfg->write($file_or_handle); + $cfg->write($file_or_handle, %hash); @@ -363,7 +429,50 @@ Returns the last node in the tree. +=head2 lint + + $cfg->lint(%ARGS); + +Configures syntax checking program to be run before saving. Takes a +hash as argument. Allowed keys are: + +=over 4 + +=item B<enable =E<gt> I<BOOL>> + +If I<BOOL> is 0, disables syntax check. Default is 1. + +=item B<command =E<gt> I<CMD>> + +Configures the command to use for syntax check. The command will be run as + + CMD FILE + +where I<FILE> is the name of the HAProxy configuration file to check. + +Default command is B<haproxy -c -f>. + +=item B<path =E<gt> I<PATH>> + +Sets the search path for the check program. I<PATH> is a colon-delimited +list of directories. Unless the first word of B<command> is an absolute +file name, it will be looked for in these directories. The first match +will be used. Default is system B<$PATH>. + +=back + +Returns the command name. + =head2 save - $cfg->save; + $cfg->save(%hash); + +Saves the parse tree in the configuration file. Syntax check will be run +prior to saving (unless previously disabled). If syntax errors are discovered, +the method will B<croak> with the appropriate diagnostics, beginning with +words C<Syntax check failed:>. + +If I<%hash> contains a non-zero B<dry_run> value, B<save> will only run syntax +check, without actually saving the file. If B<$cfg-E<gt>lint(enable =E<gt> 0)> +was called previously, this is a no-op. -Saves the parse tree in the configuration file. +Other keys in I<%hash> are the same as in B<write>, described below. |