aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-01-18 15:08:04 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-01-18 15:08:04 +0200
commitdef6f87aac7e3e7415e45e9e3ea045450bfca2d7 (patch)
treeec55c1d7d05d65ebb07b9b668641d13c43c16163
parent54204eceb2ae19a0ec9f86f65d8f0fe44569f518 (diff)
downloadacmeman-def6f87aac7e3e7415e45e9e3ea045450bfca2d7.tar.gz
acmeman-def6f87aac7e3e7415e45e9e3ea045450bfca2d7.tar.bz2
Implement full Apache reconfiguration on Slackware
This needs Apache::Config::Preproc f6db3dba or later
-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 {
159 my $dir = dirname($name); 159 my $dir = dirname($name);
160 if (! -d $dir) { 160 if (! -d $dir) {
161 debug(3, "creating directory $dir"); 161 debug(3, "creating directory $dir");
162 return if $self->dry_run_option;
162 my @created = make_path("$dir", { error => \my $err } ); 163 my @created = make_path("$dir", { error => \my $err } );
163 if (@$err) { 164 if (@$err) {
164 for my $diag (@$err) { 165 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;
3use warnings; 3use warnings;
4use Carp; 4use Carp;
5use parent 'App::Acmeman::Apache::Layout'; 5use parent 'App::Acmeman::Apache::Layout';
6use Apache::Config::Preproc;
7use App::Acmeman::Log qw(:all);
6 8
7our $PRIORITY = 10; 9our $PRIORITY = 10;
8 10
@@ -19,6 +21,184 @@ sub new {
19 } 21 }
20} 22}
21 23
24sub post_setup {
25 my ($self,$filename) = @_;
26
27 my $master_config_file = $self->config_file;
28 my $app = new Apache::Config::Preproc(
29 $master_config_file,
30 '-no-comment-grouping',
31 -expand => [ 'locus',
32 { 'include' => [ server_root => $self->apache->server_root ] },
33 { 'macro' => [
34 'keep' => [ qw(LetsEncryptChallenge
35 LetsEncryptReference
36 LetsEncryptSSL)
37 ]
38 ]
39 }
40 ])
41 or do {
42 debug(1, "can't parse apache configuration: $Apache::Admin::Config::ERROR");
43 return;
44 };
45
46 my $need_macro_module = !$self->apache_modules('macro');
47 my $letsencrypt_macro_loaded = grep {
48 $_->value =~ /^letsencrypt(?:challenge|reference|ssl)/i
49 } $app->select('section', 'Macro');
50
51 debug(3, "Need macro module? ".($need_macro_module?'yes':'no'));
52 debug(3, "Need letsencrypt macro? ".
53 ($letsencrypt_macro_loaded==0
54 ? 'yes'
55 : ($letsencrypt_macro_loaded==3
56 ? 'no' : 'perhaps')));
57
58 my $last_loadmodule;
59 my $stop_search;
60 my $last_master_locus;
61 my $include_text = "Include $filename";
62
63 foreach my $node ($app->select) {
64 if (!$stop_search) {
65 if (($node->locus->filenames)[0] eq $master_config_file) {
66 $last_master_locus = $node->locus;
67 }
68 if ($node->type eq 'section') {
69 if ($node->name =~ /^virtualhost$/i) {
70 $stop_search = $last_master_locus;
71 last;
72 }
73 }
74 }
75
76 if ($node->type eq 'comment') {
77 if ($node->value =~ m{^\s*loadmodule\s}) {
78 $last_loadmodule = $node->locus;
79 }
80 } elsif ($node->type eq 'directive') {
81 if ($node->name =~ /^loadmodule$/i) {
82 $last_loadmodule = $node->locus;
83 }
84 }
85
86 if ($need_macro_module) {
87 if ($node->type eq 'comment') {
88 if ($node->value =~ m{^\s*(loadmodule\s+macro_module\s.*)}i) {
89 debug(3, "Will uncomment ".$node->locus. " ".$node->value);
90 $self->add_command($node->locus, \&_replace_directive_at, $1);
91 $last_loadmodule = $node->locus;
92 $need_macro_module = 0;
93 }
94 }
95 }
96
97 if (!$letsencrypt_macro_loaded) {
98 if ($node->type eq 'directive'
99 && $node->name =~ /^include/i
100 && $node->value =~ m{^.+/httpd-vhosts.conf\s*$}) {
101 my $locus = $node->locus->has_file($master_config_file)
102 ? $node->locus : $last_master_locus;
103 debug(3, "Will insert \"$include_text\" before $locus");
104 $self->add_command($locus, \&_insert_directive_before,
105 $include_text);
106 $letsencrypt_macro_loaded = 3;
107 }
108 }
109 }
110
111 if ($need_macro_module && $last_loadmodule) {
112 debug(3, "Will insert a LoadModule directive after ".$last_loadmodule);
113 $self->add_command($last_loadmodule,
114 \&_insert_directive_after,
115 q{LoadModule macro_module lib64/httpd/modules/mod_macro.so});
116 $need_macro_module = 0;
117
118 $last_loadmodule->fixup_lines($app->filename => 1);
119 }
120
121 if (!$letsencrypt_macro_loaded && !$need_macro_module) {
122 if ($stop_search) {
123 debug(3, "Will insert \"$include_text\" before $stop_search");
124 $self->add_command($stop_search, \&_insert_directive_before,
125 $include_text);
126 } else {
127 debug(3, "Will insert \"$include_text\" after $last_loadmodule");
128 $self->add_command($last_loadmodule, \&_insert_directive_after,
129 $include_text);
130 }
131 }
132
133 $self->run_commands;
134}
135
136sub add_command {
137 my ($self, $locus, $command, $text) = @_;
138 my $file = ($locus->filenames)[0];
139 my $line = ($locus->filelines($file))[0];
140
141 push @{$self->{_edits}{$file}}, { line => $line, command => $command, text => $text };
142}
143
144sub run_commands {
145 my ($self) = @_;
146 foreach my $file (keys %{$self->{_edits}}) {
147 $self->run_commands_for_file($file);
148 }
149 $self->apache_modules(undef);
150}
151
152sub run_commands_for_file {
153 my ($self, $file) = @_;
154 my @commands = sort { $a->{line} <=> $b->{line} } @{$self->{_edits}{$file}};
155
156 my $app = new Apache::Config::Preproc(
157 $file,
158 '-no-comment-grouping',
159 -expand => [ 'locus' ])
160 or do {
161 error("can't parse apache configuration file $file: $Apache::Admin::Config::ERROR");
162 return;
163 };
164
165 foreach my $node ($app->select) {
166 last if (!@commands);
167 my $line = ($node->locus->filelines(($node->locus->filenames)[0]))[0];
168 if ($commands[0]->{line} == $line) {
169 my $cmd = shift @commands;
170 $self->${\ $cmd->{command} }($app, $node, $cmd->{text});
171 }
172 }
173
174 if (@commands) {
175 error((0+@commands) . " left unmatched in edit queue for file $file");
176 error("$file left unchanged");
177 } else {
178 # FIXME: backup/rollback
179 $app->save;
180 }
181}
182
183sub _replace_directive_at {
184 my ($self, $app, $node, $text) = @_;
185 $self->_insert_directive_after($app, $node, $text);
186 $node->delete;
187}
188
189sub _insert_directive_after {
190 my ($self, $app, $node, $text) = @_;
191 my ($name, $value) = split /\s+/, $text, 2;
192 $app->add('directive', $name, $value, -after => $node);
193}
194
195sub _insert_directive_before {
196 my ($self, $app, $node, $text) = @_;
197 my ($name, $value) = split /\s+/, $text, 2;
198 $app->add('directive', $name, $value, -before => $node);
199}
200
201
221; 2021;
23 203
24 204

Return to:

Send suggestions and report system problems to the System administrator.