Commit d3dd5de6cb53edec4958209d6866747c11849ec4

Authored by nollieheel
Committed by Earth Ugat
1 parent eee846a4

Bump to v0.3.1.

Revert most templates to :create action.
Integrate restriction file directives into
the virtual host files themselves.
  1 +# 0.3.1
  2 +
  3 +Revert most templates to :create action.
  4 +Integrate restriction file directives into
  5 +the virtual host files themselves.
  6 +
1 # 0.3.0 7 # 0.3.0
2 8
3 Add support for multiple FastCGI ports. 9 Add support for multiple FastCGI ports.
@@ -18,31 +18,6 @@ @@ -18,31 +18,6 @@
18 # limitations under the License. 18 # limitations under the License.
19 # 19 #
20 20
21 -# TODO defunct attribs  
22 -# The socket used PHP-FPM. If false, fastcgi is not used.  
23 -# Examples:  
24 -# '127.0.0.1:9000'  
25 -# '/var/run/php-fpm.sock'  
26 -# false  
27 -#default['cfe-nginx-php-fpm']['php_fastcgi_socket'] = '127.0.0.1:9000'  
28 -  
29 -# PHP-FPM sockets to be used. If unset, or set to string 'php-fpm-pools' (default),  
30 -# the recipe automatically gets this value from node['php-fpm']['pools'].  
31 -#default['cfe-nginx-php-fpm']['php_fastcgi_sockets'] = [  
32 -# {  
33 -# :name => 'example_socket',  
34 -# # Example values:  
35 -# # '127.0.0.1:9000'  
36 -# # '127.0.0.1:9001'  
37 -# # '/var/run/php-fpm.sock'  
38 -# :listen => '127.0.0.1:9000',  
39 -# # An optional array of comments for this socket  
40 -# :comments => []  
41 -# }  
42 -#]  
43 -  
44 -  
45 -  
46 # Setting 'update_cacert' to true will get the latest cacert from 21 # Setting 'update_cacert' to true will get the latest cacert from
47 # http://curl.haxx.se/ca/cacert.pem and use that as CAFile for postfix. 22 # http://curl.haxx.se/ca/cacert.pem and use that as CAFile for postfix.
48 default['cfe-nginx-php-fpm']['postfix']['update_cacert'] = true 23 default['cfe-nginx-php-fpm']['postfix']['update_cacert'] = true
@@ -58,15 +33,6 @@ default['cfe-nginx-php-fpm']['php-fpm']['delete_pool_www'] = true @@ -58,15 +33,6 @@ default['cfe-nginx-php-fpm']['php-fpm']['delete_pool_www'] = true
58 #default['cfe-nginx-php-fpm']['nginx']['priv_dir'] = 33 #default['cfe-nginx-php-fpm']['nginx']['priv_dir'] =
59 # "#{node['nginx']['dir']}/private" 34 # "#{node['nginx']['dir']}/private"
60 35
61 -default['cfe-nginx-php-fpm']['nginx']['restriction_file']['log_robots'] = false  
62 -default['cfe-nginx-php-fpm']['nginx']['restriction_file']['log_hidden'] = true  
63 -default['cfe-nginx-php-fpm']['nginx']['restriction_file']['log_static'] = false  
64 -default['cfe-nginx-php-fpm']['nginx']['restriction_file']['static_types'] = %w{  
65 - js css ogg ogv svg svgz eot otf woff mp4 ttf rss atom  
66 - jpg jpeg gif png ico zip tgz gz rar bz2  
67 - doc xls exe ppt tar mid midi wav bmp rtf  
68 -}  
69 -  
70 default['cfe-nginx-php-fpm']['nginx']['sites'] = [ 36 default['cfe-nginx-php-fpm']['nginx']['sites'] = [
71 #{ 37 #{
72 # Name of server. Mandatory. 38 # Name of server. Mandatory.
@@ -86,16 +52,26 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [ @@ -86,16 +52,26 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [
86 # 52 #
87 #:index => 'index.php', 53 #:index => 'index.php',
88 54
89 - # Access log options as one long string. Default: nil  
90 - #  
91 - #:access_log_options => '<some options>',  
92 -  
93 # Whether to include a default virtual server named '_' or not. 55 # Whether to include a default virtual server named '_' or not.
94 # If there is more than one server given in this 'sites' array, 56 # If there is more than one server given in this 'sites' array,
95 # :catch_all value will always be overriden to false. Default: true 57 # :catch_all value will always be overriden to false. Default: true
96 # 58 #
97 #:catch_all => true, 59 #:catch_all => true,
98 60
  61 + # Access log options as one long string. Default: nil
  62 + #
  63 + #:access_log_options => '<some options>',
  64 +
  65 + # Whether to log access to /robots.txt
  66 + # Default: false
  67 + #
  68 + #:log_robots => false,
  69 +
  70 + # Whether to log attempted accesses to hidden directories and files
  71 + # Default: true
  72 + #
  73 + #:log_hidden => true,
  74 +
99 # Necessary values for SSL/TLS setup. Default: nil 75 # Necessary values for SSL/TLS setup. Default: nil
100 # 76 #
101 #:ssl => { 77 #:ssl => {
@@ -179,6 +155,16 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [ @@ -179,6 +155,16 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [
179 # Default: (an auto-generated string) 155 # Default: (an auto-generated string)
180 # :add_statements => Additional statements to put in the config file. 156 # :add_statements => Additional statements to put in the config file.
181 # Default: [] 157 # Default: []
  158 + # :static_types => An array of strings that denote the file extensions
  159 + # to be included in a certain location directive that
  160 + # gives them a max expiration header. Set this value
  161 + # to false to disable this directive. Default: %w{
  162 + # js css ogg ogv svg svgz eot otf woff mp4 ttf
  163 + # rss atom jpg jpeg gif png ico zip tgz gz rar
  164 + # bz2 doc xls exe ppt tar mid midi wav bmp rtf
  165 + # }
  166 + # :log_static => Whether to log accesses to the above static files
  167 + # or not. Default: false
182 # 168 #
183 # Unique attributes for each type are indicated below: 169 # Unique attributes for each type are indicated below:
184 # Basic PHP Site (:type => 'basic'): 170 # Basic PHP Site (:type => 'basic'):
@@ -208,8 +194,6 @@ default['php-fpm']['emergency_restart_threshold'] = '10' @@ -208,8 +194,6 @@ default['php-fpm']['emergency_restart_threshold'] = '10'
208 default['php-fpm']['emergency_restart_interval'] = '1m' 194 default['php-fpm']['emergency_restart_interval'] = '1m'
209 default['php-fpm']['process_control_timeout'] = '10s' 195 default['php-fpm']['process_control_timeout'] = '10s'
210 default['php-fpm']['pools'] = [ 196 default['php-fpm']['pools'] = [
211 - # Most likely, just use one pool for all PHP needs.  
212 - # (But there are exceptions, of course)  
213 { 197 {
214 # Required attributes: 198 # Required attributes:
215 :name => 'example_pool', 199 :name => 'example_pool',
@@ -4,11 +4,11 @@ maintainer_email 'sysadmin@chromedia.com' @@ -4,11 +4,11 @@ maintainer_email 'sysadmin@chromedia.com'
4 license 'Apache License' 4 license 'Apache License'
5 description 'Simplifies setup of Nginx+PHP-FPM in Chromedia.' 5 description 'Simplifies setup of Nginx+PHP-FPM in Chromedia.'
6 long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) 6 long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
7 -version '0.3.0' 7 +version '0.3.1'
8 8
9 { 9 {
10 'php-fpm' => '0.7.5', 10 'php-fpm' => '0.7.5',
11 - 'mariadb' => '0.2.12', 11 + 'mariadb' => '0.3.1',
12 'postfix' => '3.6.2', 12 'postfix' => '3.6.2',
13 'nginx' => '2.7.6' 13 'nginx' => '2.7.6'
14 }.each { |cb, ver| depends cb, '~> ' + ver } 14 }.each { |cb, ver| depends cb, '~> ' + ver }
@@ -28,20 +28,6 @@ priv_dir = node['cfe-nginx-php-fpm']['nginx']['priv_dir'] @@ -28,20 +28,6 @@ priv_dir = node['cfe-nginx-php-fpm']['nginx']['priv_dir']
28 end 28 end
29 end 29 end
30 30
31 -# The restrictions file containing default rules for virtual servers.  
32 -path_rest = "#{inc_dir}/inc_restrictions"  
33 -restfa = node['cfe-nginx-php-fpm']['nginx']['restriction_file']  
34 -template path_rest do  
35 - action :create_if_missing  
36 - mode 0644  
37 - variables(  
38 - :log_robots => restfa['log_robots'],  
39 - :log_hidden => restfa['log_hidden'],  
40 - :log_static => restfa['log_static'],  
41 - :static_types => restfa['static_types']  
42 - )  
43 -end  
44 -  
45 # Generate config files for each virtual server. 31 # Generate config files for each virtual server.
46 catch_all_def_false = node['cfe-nginx-php-fpm']['nginx']['sites'].length > 1 32 catch_all_def_false = node['cfe-nginx-php-fpm']['nginx']['sites'].length > 1
47 33
@@ -65,6 +51,9 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -65,6 +51,9 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
65 site_ss1 = site[:server_statements_1] || [] 51 site_ss1 = site[:server_statements_1] || []
66 site_ss2 = site[:server_statements_2] || [] 52 site_ss2 = site[:server_statements_2] || []
67 53
  54 + site_logrobots = site.has_key?(:log_robots) ? site[:log_robots] : false
  55 + site_loghidden = site.has_key?(:log_hidden) ? site[:log_hidden] : true
  56 +
68 temp_catch_all = site.has_key?(:catch_all) ? site[:catch_all] : true 57 temp_catch_all = site.has_key?(:catch_all) ? site[:catch_all] : true
69 site_catch_all = catch_all_def_false ? false : temp_catch_all 58 site_catch_all = catch_all_def_false ? false : temp_catch_all
70 site_types = ( site[:types] || [] ).uniq { |e| e[:type] } 59 site_types = ( site[:types] || [] ).uniq { |e| e[:type] }
@@ -75,6 +64,11 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -75,6 +64,11 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
75 'X-Permitted-Cross-Domain-Policies' => 'none' 64 'X-Permitted-Cross-Domain-Policies' => 'none'
76 } 65 }
77 66
  67 + path_crt = ''
  68 + path_key = ''
  69 + path_dhparam = ''
  70 + path_pass = ''
  71 +
78 # If TLS/SSL is enabled, configure it: 72 # If TLS/SSL is enabled, configure it:
79 if site_ssl 73 if site_ssl
80 if site_ssl[:letsencrypt] 74 if site_ssl[:letsencrypt]
@@ -118,11 +112,6 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -118,11 +112,6 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
118 execute "openssl dhparam -out #{path_dhparam} #{dh_modulus}" do 112 execute "openssl dhparam -out #{path_dhparam} #{dh_modulus}" do
119 not_if { ::File.exist?(path_dhparam) } 113 not_if { ::File.exist?(path_dhparam) }
120 end 114 end
121 -  
122 - else  
123 - path_crt = ''  
124 - path_key = ''  
125 - path_dhparam = ''  
126 end 115 end
127 116
128 # If basic auth is enabled, create htpasswd file 117 # If basic auth is enabled, create htpasswd file
@@ -135,16 +124,13 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -135,16 +124,13 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
135 "\\n\" >> #{path_pass}" 124 "\\n\" >> #{path_pass}"
136 action :run 125 action :run
137 sensitive true 126 sensitive true
138 - not_if { ::File.exist?(path_pass) }  
139 end 127 end
140 end 128 end
141 - else  
142 - path_pass = ''  
143 end 129 end
144 130
145 - site_includes = [path_rest]  
146 - upstreams = []  
147 - # upstreams element: 131 + site_includes = []
  132 + site_upstreams = []
  133 + # site_upstreams element:
148 # { 134 # {
149 # :name => 'string', 135 # :name => 'string',
150 # :servers => [ 136 # :servers => [
@@ -155,13 +141,35 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -155,13 +141,35 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
155 141
156 # Create necessary include files for each type of this site 142 # Create necessary include files for each type of this site
157 site_types.each do |stype| 143 site_types.each do |stype|
  144 +
  145 + # Set default attributes for each site type
158 stype_subp = stype[:subpath] ? stype[:subpath].gsub(/^\/+|\/+$|\s/, '') : '' 146 stype_subp = stype[:subpath] ? stype[:subpath].gsub(/^\/+|\/+$|\s/, '') : ''
159 stype_subp = stype_subp.length > 0 ? "#{stype_subp}/" : stype_subp 147 stype_subp = stype_subp.length > 0 ? "#{stype_subp}/" : stype_subp
160 - stype_ads = stype[:add_statements] || []  
161 - stype_ups = stype[:upstream_name] || 148 +
  149 + stype_ads = stype[:add_statements] || []
  150 + stype_ups = stype[:upstream_name] ||
162 "#{stype[:type]}_#{site_sname.gsub('.', '_')}" 151 "#{stype[:type]}_#{site_sname.gsub('.', '_')}"
163 152
164 - upstreams.push( { 153 + stype_logstatic = stype.has_key?(:log_static) ? stype[:log_static] : false
  154 + stype_statics = if stype.has_key?(:static_types)
  155 + stype[:static_types]
  156 + else
  157 + %w{
  158 + js css ogg ogv svg svgz eot otf woff mp4 ttf rss atom
  159 + jpg jpeg gif png ico zip tgz gz rar bz2
  160 + doc xls exe ppt tar mid midi wav bmp rtf
  161 + }
  162 + end
  163 +
  164 + vars = {
  165 + :subpath => stype_subp,
  166 + :upstream_name => stype_ups,
  167 + :add_statements => stype_ads,
  168 + :static_types => stype_statics,
  169 + :log_static => stype_logstatic
  170 + }
  171 +
  172 + site_upstreams.push( {
165 :name => stype_ups, 173 :name => stype_ups,
166 :servers => stype[:upstream_servers] || [] 174 :servers => stype[:upstream_servers] || []
167 } ) 175 } )
@@ -169,40 +177,30 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -169,40 +177,30 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
169 case stype[:type] 177 case stype[:type]
170 # BASIC PHP SITE 178 # BASIC PHP SITE
171 when 'basic' 179 when 'basic'
172 - stype_intererror = stype.has_key?(:fastcgi_intercept_errors) ? 180 + vars[:index] = site_index
  181 + vars[:fastcgi_intercept_errors] =
  182 + stype.has_key?(:fastcgi_intercept_errors) ?
173 stype[:fastcgi_intercept_errors] : false 183 stype[:fastcgi_intercept_errors] : false
174 184
175 template "#{inc_dir}/inc_type_basic_#{site_sname}" do 185 template "#{inc_dir}/inc_type_basic_#{site_sname}" do
176 source 'inc_type_basic.erb' 186 source 'inc_type_basic.erb'
177 mode 0644 187 mode 0644
178 - action :create_if_missing  
179 - variables(  
180 - :index => site_index,  
181 - :subpath => stype_subp,  
182 - :upstream_name => stype_ups,  
183 - :add_statements => stype_ads,  
184 - :fastcgi_intercept_errors => stype_intererror  
185 - ) 188 + variables vars
186 end 189 end
187 site_includes.push("#{inc_dir}/inc_type_basic_#{site_sname}") 190 site_includes.push("#{inc_dir}/inc_type_basic_#{site_sname}")
188 191
189 # STANDARD WORDPRESS SITE 192 # STANDARD WORDPRESS SITE
190 when 'wordpress' 193 when 'wordpress'
191 - stype_intererror = stype.has_key?(:fastcgi_intercept_errors) ? 194 + vars[:index] = site_index
  195 + vars[:loginpage_statements] = stype[:loginpage_statements] || []
  196 + vars[:fastcgi_intercept_errors] =
  197 + stype.has_key?(:fastcgi_intercept_errors) ?
192 stype[:fastcgi_intercept_errors] : false 198 stype[:fastcgi_intercept_errors] : false
193 199
194 template "#{inc_dir}/inc_type_wordpress_#{site_sname}" do 200 template "#{inc_dir}/inc_type_wordpress_#{site_sname}" do
195 source 'inc_type_wordpress.erb' 201 source 'inc_type_wordpress.erb'
196 mode 0644 202 mode 0644
197 - action :create_if_missing  
198 - variables(  
199 - :index => site_index,  
200 - :subpath => stype_subp,  
201 - :upstream_name => stype_ups,  
202 - :add_statements => stype_ads,  
203 - :loginpage_statements => stype[:loginpage_statements] || [],  
204 - :fastcgi_intercept_errors => stype_intererror  
205 - ) 203 + variables vars
206 end 204 end
207 site_includes.push("#{inc_dir}/inc_type_wordpress_#{site_sname}") 205 site_includes.push("#{inc_dir}/inc_type_wordpress_#{site_sname}")
208 206
@@ -211,12 +209,7 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -211,12 +209,7 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
211 template "#{inc_dir}/inc_type_webserver_#{site_sname}" do 209 template "#{inc_dir}/inc_type_webserver_#{site_sname}" do
212 source 'inc_type_webserver.erb' 210 source 'inc_type_webserver.erb'
213 mode 0644 211 mode 0644
214 - action :create_if_missing  
215 - variables(  
216 - :subpath => stype_subp,  
217 - :upstream_name => stype_ups,  
218 - :add_statements => stype_ads  
219 - ) 212 + variables vars
220 end 213 end
221 site_ins.push("map $http_upgrade $connection_upgrade {\n"\ 214 site_ins.push("map $http_upgrade $connection_upgrade {\n"\
222 " default upgrade;\n"\ 215 " default upgrade;\n"\
@@ -233,7 +226,6 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -233,7 +226,6 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
233 # Create the main config file for this site 226 # Create the main config file for this site
234 template "#{node['nginx']['dir']}/sites-available/#{site_sname}" do 227 template "#{node['nginx']['dir']}/sites-available/#{site_sname}" do
235 source 'nginx_site.conf.erb' 228 source 'nginx_site.conf.erb'
236 - action :create_if_missing  
237 mode 0644 229 mode 0644
238 notifies :restart, 'service[nginx]', :delayed 230 notifies :restart, 'service[nginx]', :delayed
239 variables( 231 variables(
@@ -244,15 +236,17 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site| @@ -244,15 +236,17 @@ node['cfe-nginx-php-fpm']['nginx']['sites'].each do |site|
244 :ssl => site_ssl, 236 :ssl => site_ssl,
245 :auth => site_auth, 237 :auth => site_auth,
246 238
247 - :access_log_options => site_alo,  
248 :catch_all => site_catch_all, 239 :catch_all => site_catch_all,
  240 + :access_log_options => site_alo,
  241 + :log_robots => site_logrobots,
  242 + :log_hidden => site_loghidden,
249 243
250 :path_crt => path_crt, 244 :path_crt => path_crt,
251 :path_key => path_key, 245 :path_key => path_key,
252 :path_pass => path_pass, 246 :path_pass => path_pass,
253 :path_dhparam => path_dhparam, 247 :path_dhparam => path_dhparam,
254 248
255 - :upstreams => upstreams, 249 + :upstreams => site_upstreams,
256 :includes => site_includes, 250 :includes => site_includes,
257 :init_statements => site_ins, 251 :init_statements => site_ins,
258 :add_headers => site_aheads, 252 :add_headers => site_aheads,
@@ -2,6 +2,17 @@ @@ -2,6 +2,17 @@
2 # 2 #
3 # A basic PHP site config. 3 # A basic PHP site config.
4 4
  5 +<% if @static_types -%>
  6 +# Send expires headers and (probably?) turn off 404 error logging.
  7 +location ~* ^/<%= @subpath %>.+\.(<%= @static_types.join('|') %>)$ {
  8 + expires max;
  9 +<% unless @log_static -%>
  10 + log_not_found off;
  11 + access_log off;
  12 +<% end -%>
  13 +}
  14 +
  15 +<% end -%>
5 <% @add_statements.each do |ads| -%> 16 <% @add_statements.each do |ads| -%>
6 <%= ads %> 17 <%= ads %>
7 18
@@ -6,6 +6,17 @@ if ($http_user_agent ~ "MSIE") { @@ -6,6 +6,17 @@ if ($http_user_agent ~ "MSIE") {
6 return 303 https://browser-update.org/update.html; 6 return 303 https://browser-update.org/update.html;
7 } 7 }
8 8
  9 +<% if @static_types -%>
  10 +# Send expires headers and (probably?) turn off 404 error logging.
  11 +location ~* ^/<%= @subpath %>.+\.(<%= @static_types.join('|') %>)$ {
  12 + expires max;
  13 +<% unless @log_static -%>
  14 + log_not_found off;
  15 + access_log off;
  16 +<% end -%>
  17 +}
  18 +
  19 +<% end -%>
9 <% @add_statements.each do |ads| -%> 20 <% @add_statements.each do |ads| -%>
10 <%= ads %> 21 <%= ads %>
11 22
@@ -6,6 +6,17 @@ @@ -6,6 +6,17 @@
6 # Add trailing slash to */wp-admin requests. 6 # Add trailing slash to */wp-admin requests.
7 rewrite /<%= @subpath %>wp-admin$ $scheme://$host$uri/ permanent; 7 rewrite /<%= @subpath %>wp-admin$ $scheme://$host$uri/ permanent;
8 8
  9 +<% if @static_types -%>
  10 +# Send expires headers and (probably?) turn off 404 error logging.
  11 +location ~* ^/<%= @subpath %>.+\.(<%= @static_types.join('|') %>)$ {
  12 + expires max;
  13 +<% unless @log_static -%>
  14 + log_not_found off;
  15 + access_log off;
  16 +<% end -%>
  17 +}
  18 +
  19 +<% end -%>
9 <% @add_statements.each do |ads| -%> 20 <% @add_statements.each do |ads| -%>
10 <%= ads %> 21 <%= ads %>
11 22
@@ -120,6 +120,28 @@ server { @@ -120,6 +120,28 @@ server {
120 access_log <%= @log_dir %>/<%= @server_name %>.access.log<% if @access_log_options %> <%= @access_log_options %><% end %>; 120 access_log <%= @log_dir %>/<%= @server_name %>.access.log<% if @access_log_options %> <%= @access_log_options %><% end %>;
121 error_log <%= @log_dir %>/<%= @server_name %>.error.log; 121 error_log <%= @log_dir %>/<%= @server_name %>.error.log;
122 122
  123 + location = /favicon.ico {
  124 + log_not_found off;
  125 + access_log off;
  126 + }
  127 +
  128 + location = /robots.txt {
  129 + allow all;
  130 +<% unless @log_robots -%>
  131 + log_not_found off;
  132 + access_log off;
  133 +<% end -%>
  134 + }
  135 +
  136 + # Deny all attempts to access hidden files and folders
  137 + location ~ (^|/)\. {
  138 + deny all;
  139 +<% unless @log_hidden -%>
  140 + log_not_found off;
  141 + access_log off;
  142 +<% end -%>
  143 + }
  144 +
123 <% @server_statements_1.each do |s1| -%> 145 <% @server_statements_1.each do |s1| -%>
124 <%= sm %> 146 <%= sm %>
125 <% end -%> 147 <% end -%>