Add `quote` function to templatesymlink managed templates

In order to correctly handle the emitting of strings correctly escaped
for use in a YAML file, we add a `quote` helper function, and remove the
older `single_quote` helper.

* Adds QuoteHelper with new `quote` function
* Adds spec examples `quote` helper function
* Converts existing uses of `single_quote` to `quote`
* Removes SingleQuoteHelper

This may cause a slight bump if external code is using SingleQuoteHelper,
though these are all internal cookbooks to manage omnibus-gitlab.
This commit is contained in:
Richard Clamp 2017-08-31 16:47:56 +01:00
parent 67210a1c50
commit fdc6a93baa
9 changed files with 110 additions and 45 deletions

View File

@ -8,14 +8,14 @@ production:
collation: <%= @db_collation %>
database: <%= @db_database %>
pool: <%= @db_pool %>
username: <%= single_quote(@db_username) %>
password: <%= single_quote(@db_password) %>
host: <%= single_quote(@db_host) %>
username: <%= quote(@db_username) %>
password: <%= quote(@db_password) %>
host: <%= quote(@db_host) %>
port: <%= @db_port %>
socket: <%= single_quote(@db_socket) %>
sslmode: <%= single_quote(@db_sslmode) %>
sslrootcert: <%= single_quote(@db_sslrootcert) || single_quote(@db_sslca) %>
sslca: <%= single_quote(@db_sslca) || single_quote(@db_sslrootcert) %>
socket: <%= quote(@db_socket) %>
sslmode: <%= quote(@db_sslmode) %>
sslrootcert: <%= quote(@db_sslrootcert) || quote(@db_sslca) %>
sslca: <%= quote(@db_sslca) || quote(@db_sslrootcert) %>
load_balancing: <%= @db_load_balancing.to_json %>
prepared_statements: <%= @db_prepared_statements %>
statements_limit: <%= @db_statements_limit %>

View File

@ -35,7 +35,7 @@ production: &base
user: <%= node['gitlab']['user']['username'] %>
## Date & Time settings
time_zone: <%= single_quote(@time_zone) %>
time_zone: <%= quote(@time_zone) %>
## Email settings
# Uncomment and set to false if you need to disable email sending from GitLab (default: true)
@ -65,7 +65,7 @@ production: &base
# This happens when the commit is pushed or merged into the default branch of a project.
# When not specified the default issue_closing_pattern as specified below will be used.
# Tip: you can test your closing pattern at http://rubular.com
issue_closing_pattern: <%= single_quote(@gitlab_issue_closing_pattern) %>
issue_closing_pattern: <%= quote(@gitlab_issue_closing_pattern) %>
## Default project features settings
default_projects_features:
@ -95,17 +95,17 @@ production: &base
# The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
# The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
address: <%= single_quote(@incoming_email_address) %>
address: <%= quote(@incoming_email_address) %>
# Email account username
# With third party providers, this is usually the full email address.
# With self-hosted email servers, this is usually the user part of the email address.
user: <%= single_quote(@incoming_email_email) %>
user: <%= quote(@incoming_email_email) %>
# Email account password
password: <%= single_quote(@incoming_email_password) %>
password: <%= quote(@incoming_email_password) %>
# IMAP server host
host: <%= single_quote(@incoming_email_host) %>
host: <%= quote(@incoming_email_host) %>
# IMAP server port
port: <%= @incoming_email_port %>
# Whether the IMAP server uses SSL
@ -114,7 +114,7 @@ production: &base
start_tls: <%= @incoming_email_start_tls %>
# The mailbox where incoming mail will end up. Usually "inbox".
mailbox: <%= single_quote(@incoming_email_mailbox_name) %>
mailbox: <%= quote(@incoming_email_mailbox_name) %>
# The IDLE command timeout.
idle_timeout: <%= @incoming_email_idle_timeout %>
@ -125,7 +125,7 @@ production: &base
path: <%= @artifacts_path %>
object_store:
enabled: <%= @artifacts_object_store_enabled %>
remote_directory: <%= single_quote(@artifacts_object_store_remote_directory) %>
remote_directory: <%= quote(@artifacts_object_store_remote_directory) %>
connection: <%= @artifacts_object_store_connection.to_json %>
## Git LFS
@ -162,8 +162,8 @@ production: &base
## For Libravatar see: https://docs.gitlab.com/ce/customization/libravatar.html
gravatar:
# gravatar urls: possible placeholders: %{hash} %{size} %{email}
plain_url: <%= single_quote(@gravatar_plain_url) %> # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
ssl_url: <%= single_quote(@gravatar_ssl_url) %> # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
plain_url: <%= quote(@gravatar_plain_url) %> # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
ssl_url: <%= quote(@gravatar_ssl_url) %> # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
## Auxiliary jobs
# Periodically executed jobs, to self-heal GitLab, do external synchronizations, etc.
@ -260,21 +260,21 @@ production: &base
<%= provider_id %>: <%= settings.to_json %>
<% end %>
<% else %>
host: <%= single_quote(@ldap_host) %>
host: <%= quote(@ldap_host) %>
port: <%= @ldap_port %>
uid: <%= single_quote(@ldap_uid) %>
method: <%= single_quote(@ldap_method) %> # "tls" or "ssl" or "plain"
bind_dn: <%= single_quote(@ldap_bind_dn) %>
password: <%= single_quote(@ldap_password) %>
uid: <%= quote(@ldap_uid) %>
method: <%= quote(@ldap_method) %> # "tls" or "ssl" or "plain"
bind_dn: <%= quote(@ldap_bind_dn) %>
password: <%= quote(@ldap_password) %>
active_directory: <%= @ldap_active_directory %>
allow_username_or_email_login: <%= @ldap_allow_username_or_email_login %>
base: <%= single_quote(@ldap_base) %>
user_filter: <%= single_quote(@ldap_user_filter) %>
base: <%= quote(@ldap_base) %>
user_filter: <%= quote(@ldap_user_filter) %>
## EE only
group_base: <%= single_quote(@ldap_group_base) %>
admin_group: <%= single_quote(@ldap_admin_group) %>
sync_ssh_keys: <%= single_quote(@ldap_sync_ssh_keys) %>
group_base: <%= quote(@ldap_group_base) %>
admin_group: <%= quote(@ldap_admin_group) %>
sync_ssh_keys: <%= quote(@ldap_sync_ssh_keys) %>
sync_time: <%= @ldap_sync_time %>
<% end %>
@ -392,7 +392,7 @@ production: &base
# Fog storage connection settings, see http://fog.io/storage/ .
connection: <%= @backup_upload_connection.to_json if @backup_upload_connection %>
# The remote 'directory' to store your backups. For S3, this would be the bucket name.
remote_directory: <%= single_quote(@backup_upload_remote_directory) %>
remote_directory: <%= quote(@backup_upload_remote_directory) %>
multipart_chunk_size: <%= @backup_multipart_chunk_size %>
encryption: <%= @backup_encryption %>
storage_class: <%= @backup_storage_class %>
@ -446,13 +446,13 @@ production: &base
extra:
<% if @extra_google_analytics_id %>
## Google analytics. Uncomment if you want it
google_analytics_id: <%= single_quote(@extra_google_analytics_id) %>
google_analytics_id: <%= quote(@extra_google_analytics_id) %>
<% end %>
<% if @extra_piwik_url %>
## Piwik analytics.
piwik_url: <%= single_quote(@extra_piwik_url) %>
piwik_site_id: <%= single_quote(@extra_piwik_site_id) %>
piwik_url: <%= quote(@extra_piwik_url) %>
piwik_site_id: <%= quote(@extra_piwik_site_id) %>
<% end %>
rack_attack:

View File

@ -20,4 +20,4 @@ require 'digest'
require_relative 'helpers/redhat_helper'
require_relative 'helpers/secrets_helper'
require_relative 'helpers/version_helper'
require_relative 'helpers/single_quote_helper'
require_relative 'helpers/quote_helper'

View File

@ -0,0 +1,5 @@
module QuoteHelper
def quote(string)
string.to_s.inspect unless string.nil?
end
end

View File

@ -1,5 +0,0 @@
module SingleQuoteHelper
def single_quote(string)
"'#{string}'" unless string.nil?
end
end

View File

@ -28,7 +28,7 @@ property :group, String
property :mode, String
property :cookbook, String
property :variables, Hash, default: {}
property :helpers, Module, default: SingleQuoteHelper
property :helpers, Module, default: QuoteHelper
property :notifies, Array
property :restarts, Array, default: []
property :sensitive, [true, false], default: false

View File

@ -50,7 +50,7 @@ describe 'gitlab-ee::geo-secondary' do
group: 'root',
mode: '0644'
)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database_geo.yml').with_content(/host: \'\/var\/opt\/gitlab\/geo-postgresql\'/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database_geo.yml').with_content(/host: \"\/var\/opt\/gitlab\/geo-postgresql\"/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database_geo.yml').with_content(/database: gitlabhq_geo_production/)
end

View File

@ -138,7 +138,7 @@ describe 'gitlab::gitlab-rails' do
context 'for settings regarding object storage for artifacts' do
it 'allows not setting any values' do
expect(chef_run).to render_file(gitlab_yml_path)
.with_content(/object_store:\s+enabled: false\s+remote_directory: 'artifacts'\s+connection:/)
.with_content(/object_store:\s+enabled: false\s+remote_directory: "artifacts"\s+connection:/)
end
it 'sets the connection in YAML' do
@ -158,7 +158,7 @@ describe 'gitlab::gitlab-rails' do
})
expect(chef_run).to render_file(gitlab_yml_path)
.with_content(/object_store:\s+enabled: true\s+remote_directory:\s+'mepmep'/)
.with_content(/object_store:\s+enabled: true\s+remote_directory:\s+"mepmep"/)
expect(chef_run).to render_file(gitlab_yml_path)
.with_content(/connection:\s"{\\n 'provider' => 'AWS'/)
expect(chef_run).to render_file(gitlab_yml_path)
@ -545,7 +545,7 @@ describe 'gitlab::gitlab-rails' do
group: 'root',
mode: '0644'
)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: \'\/var\/opt\/gitlab\/postgresql\'/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: \"\/var\/opt\/gitlab\/postgresql\"/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/database: gitlabhq_production/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/load_balancing: {"hosts":\[\]}/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/prepared_statements: true/)
@ -578,14 +578,14 @@ describe 'gitlab::gitlab-rails' do
end
it 'creates the postgres configuration file with multi listen_address and database.yml file with one host' do
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: '127.0.0.1'/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: "127.0.0.1"/)
expect(chef_run).to render_file('/var/opt/gitlab/postgresql/data/postgresql.conf').with_content(/listen_addresses = '127.0.0.1,1.1.1.1'/)
end
end
context 'when no postgresql listen_address is used' do
it 'creates the postgres configuration file with empty listen_address and database.yml file with default one' do
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: '\/var\/opt\/gitlab\/postgresql'/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: "\/var\/opt\/gitlab\/postgresql"/)
expect(chef_run).to render_file('/var/opt/gitlab/postgresql/data/postgresql.conf').with_content(/listen_addresses = ''/)
end
end
@ -600,7 +600,7 @@ describe 'gitlab::gitlab-rails' do
end
it 'creates the postgres configuration file with one listen_address and database.yml file with one host' do
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: '127.0.0.1'/)
expect(chef_run).to render_file('/var/opt/gitlab/gitlab-rails/etc/database.yml').with_content(/host: "127.0.0.1"/)
expect(chef_run).to render_file('/var/opt/gitlab/postgresql/data/postgresql.conf').with_content(/listen_addresses = '127.0.0.1'/)
end

View File

@ -0,0 +1,65 @@
require 'chef_helper'
describe QuoteHelper do
include QuoteHelper
describe "#quote" do
context 'handling nil' do
it 'should return nil' do
expect(quote(nil)).to eq(nil)
end
end
context 'handling numbers' do
it 'should cooerce numbers to strings' do
result = quote(42)
expect(result).to be_instance_of(String)
expect(result).to eq('"42"')
end
end
context 'roundtripping values via YAML' do
values = [
"foo",
# single quotes
"foo'",
"'foo",
"fo'o",
"'foo'",
# double quotes
'foo"',
'"foo',
'fo"o',
'"foo"',
# newlines
"foo\n",
"\nfoo",
"fo\no",
"\nfoo\n",
# tabs
"foo\t",
"\tfoo",
"fo\to",
"\tfoo\t",
# spaces
"foo ",
" foo",
"fo o",
" foo ",
# unicode snowman
"foo☃",
"☃foo",
"fo☃o",
"☃foo☃",
]
values.each do |value|
it "should YAML roundtrip #{value.inspect}" do
# create a document with structure { 'value' : quote(value) }
yaml_document = "---\nvalue: #{quote(value)}"
document = YAML.safe_load(yaml_document)
expect(document['value']).to eq(value)
end
end
end
end
end