diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-01-18 15:08:04 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-01-18 15:08:04 +0200 |
commit | def6f87aac7e3e7415e45e9e3ea045450bfca2d7 (patch) | |
tree | ec55c1d7d05d65ebb07b9b668641d13c43c16163 | |
parent | 54204eceb2ae19a0ec9f86f65d8f0fe44569f518 (diff) | |
download | acmeman-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.pm | 1 | ||||
-rw-r--r-- | lib/App/Acmeman/Apache/Layout/slackware.pm | 180 |
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; | |||
3 | use warnings; | 3 | use warnings; |
4 | use Carp; | 4 | use Carp; |
5 | use parent 'App::Acmeman::Apache::Layout'; | 5 | use parent 'App::Acmeman::Apache::Layout'; |
6 | use Apache::Config::Preproc; | ||
7 | use App::Acmeman::Log qw(:all); | ||
6 | 8 | ||
7 | our $PRIORITY = 10; | 9 | our $PRIORITY = 10; |
8 | 10 | ||
@@ -19,6 +21,184 @@ sub new { | |||
19 | } | 21 | } |
20 | } | 22 | } |
21 | 23 | ||
24 | sub 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 | |||
136 | sub 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 | |||
144 | sub 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 | |||
152 | sub 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 | |||
183 | sub _replace_directive_at { | ||
184 | my ($self, $app, $node, $text) = @_; | ||
185 | $self->_insert_directive_after($app, $node, $text); | ||
186 | $node->delete; | ||
187 | } | ||
188 | |||
189 | sub _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 | |||
195 | sub _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 | |||
22 | 1; | 202 | 1; |
23 | 203 | ||
24 | 204 | ||