aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/App/Acmeman.pm1
-rw-r--r--lib/App/Acmeman/Apache/Layout/slackware.pm180
2 files changed, 181 insertions, 0 deletions
diff --git a/lib/App/Acmeman.pm b/lib/App/Acmeman.pm
index dba6d3b..fafcb09 100644
--- a/lib/App/Acmeman.pm
+++ b/lib/App/Acmeman.pm
@@ -159,6 +159,7 @@ sub prep_dir {
my $dir = dirname($name);
if (! -d $dir) {
debug(3, "creating directory $dir");
+ return if $self->dry_run_option;
my @created = make_path("$dir", { error => \my $err } );
if (@$err) {
for my $diag (@$err) {
diff --git a/lib/App/Acmeman/Apache/Layout/slackware.pm b/lib/App/Acmeman/Apache/Layout/slackware.pm
index 89297fc..d09017a 100644
--- a/lib/App/Acmeman/Apache/Layout/slackware.pm
+++ b/lib/App/Acmeman/Apache/Layout/slackware.pm
@@ -3,6 +3,8 @@ use strict;
use warnings;
use Carp;
use parent 'App::Acmeman::Apache::Layout';
+use Apache::Config::Preproc;
+use App::Acmeman::Log qw(:all);
our $PRIORITY = 10;
@@ -19,6 +21,184 @@ sub new {
}
}
+sub post_setup {
+ my ($self,$filename) = @_;
+
+ my $master_config_file = $self->config_file;
+ my $app = new Apache::Config::Preproc(
+ $master_config_file,
+ '-no-comment-grouping',
+ -expand => [ 'locus',
+ { 'include' => [ server_root => $self->apache->server_root ] },
+ { 'macro' => [
+ 'keep' => [ qw(LetsEncryptChallenge
+ LetsEncryptReference
+ LetsEncryptSSL)
+ ]
+ ]
+ }
+ ])
+ or do {
+ debug(1, "can't parse apache configuration: $Apache::Admin::Config::ERROR");
+ return;
+ };
+
+ my $need_macro_module = !$self->apache_modules('macro');
+ my $letsencrypt_macro_loaded = grep {
+ $_->value =~ /^letsencrypt(?:challenge|reference|ssl)/i
+ } $app->select('section', 'Macro');
+
+ debug(3, "Need macro module? ".($need_macro_module?'yes':'no'));
+ debug(3, "Need letsencrypt macro? ".
+ ($letsencrypt_macro_loaded==0
+ ? 'yes'
+ : ($letsencrypt_macro_loaded==3
+ ? 'no' : 'perhaps')));
+
+ my $last_loadmodule;
+ my $stop_search;
+ my $last_master_locus;
+ my $include_text = "Include $filename";
+
+ foreach my $node ($app->select) {
+ if (!$stop_search) {
+ if (($node->locus->filenames)[0] eq $master_config_file) {
+ $last_master_locus = $node->locus;
+ }
+ if ($node->type eq 'section') {
+ if ($node->name =~ /^virtualhost$/i) {
+ $stop_search = $last_master_locus;
+ last;
+ }
+ }
+ }
+
+ if ($node->type eq 'comment') {
+ if ($node->value =~ m{^\s*loadmodule\s}) {
+ $last_loadmodule = $node->locus;
+ }
+ } elsif ($node->type eq 'directive') {
+ if ($node->name =~ /^loadmodule$/i) {
+ $last_loadmodule = $node->locus;
+ }
+ }
+
+ if ($need_macro_module) {
+ if ($node->type eq 'comment') {
+ if ($node->value =~ m{^\s*(loadmodule\s+macro_module\s.*)}i) {
+ debug(3, "Will uncomment ".$node->locus. " ".$node->value);
+ $self->add_command($node->locus, \&_replace_directive_at, $1);
+ $last_loadmodule = $node->locus;
+ $need_macro_module = 0;
+ }
+ }
+ }
+
+ if (!$letsencrypt_macro_loaded) {
+ if ($node->type eq 'directive'
+ && $node->name =~ /^include/i
+ && $node->value =~ m{^.+/httpd-vhosts.conf\s*$}) {
+ my $locus = $node->locus->has_file($master_config_file)
+ ? $node->locus : $last_master_locus;
+ debug(3, "Will insert \"$include_text\" before $locus");
+ $self->add_command($locus, \&_insert_directive_before,
+ $include_text);
+ $letsencrypt_macro_loaded = 3;
+ }
+ }
+ }
+
+ if ($need_macro_module && $last_loadmodule) {
+ debug(3, "Will insert a LoadModule directive after ".$last_loadmodule);
+ $self->add_command($last_loadmodule,
+ \&_insert_directive_after,
+ q{LoadModule macro_module lib64/httpd/modules/mod_macro.so});
+ $need_macro_module = 0;
+
+ $last_loadmodule->fixup_lines($app->filename => 1);
+ }
+
+ if (!$letsencrypt_macro_loaded && !$need_macro_module) {
+ if ($stop_search) {
+ debug(3, "Will insert \"$include_text\" before $stop_search");
+ $self->add_command($stop_search, \&_insert_directive_before,
+ $include_text);
+ } else {
+ debug(3, "Will insert \"$include_text\" after $last_loadmodule");
+ $self->add_command($last_loadmodule, \&_insert_directive_after,
+ $include_text);
+ }
+ }
+
+ $self->run_commands;
+}
+
+sub add_command {
+ my ($self, $locus, $command, $text) = @_;
+ my $file = ($locus->filenames)[0];
+ my $line = ($locus->filelines($file))[0];
+
+ push @{$self->{_edits}{$file}}, { line => $line, command => $command, text => $text };
+}
+
+sub run_commands {
+ my ($self) = @_;
+ foreach my $file (keys %{$self->{_edits}}) {
+ $self->run_commands_for_file($file);
+ }
+ $self->apache_modules(undef);
+}
+
+sub run_commands_for_file {
+ my ($self, $file) = @_;
+ my @commands = sort { $a->{line} <=> $b->{line} } @{$self->{_edits}{$file}};
+
+ my $app = new Apache::Config::Preproc(
+ $file,
+ '-no-comment-grouping',
+ -expand => [ 'locus' ])
+ or do {
+ error("can't parse apache configuration file $file: $Apache::Admin::Config::ERROR");
+ return;
+ };
+
+ foreach my $node ($app->select) {
+ last if (!@commands);
+ my $line = ($node->locus->filelines(($node->locus->filenames)[0]))[0];
+ if ($commands[0]->{line} == $line) {
+ my $cmd = shift @commands;
+ $self->${\ $cmd->{command} }($app, $node, $cmd->{text});
+ }
+ }
+
+ if (@commands) {
+ error((0+@commands) . " left unmatched in edit queue for file $file");
+ error("$file left unchanged");
+ } else {
+ # FIXME: backup/rollback
+ $app->save;
+ }
+}
+
+sub _replace_directive_at {
+ my ($self, $app, $node, $text) = @_;
+ $self->_insert_directive_after($app, $node, $text);
+ $node->delete;
+}
+
+sub _insert_directive_after {
+ my ($self, $app, $node, $text) = @_;
+ my ($name, $value) = split /\s+/, $text, 2;
+ $app->add('directive', $name, $value, -after => $node);
+}
+
+sub _insert_directive_before {
+ my ($self, $app, $node, $text) = @_;
+ my ($name, $value) = split /\s+/, $text, 2;
+ $app->add('directive', $name, $value, -before => $node);
+}
+
+
1;

Return to:

Send suggestions and report system problems to the System administrator.