diff --git a/doc/settings/redis.md b/doc/settings/redis.md index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_ZG9jL3NldHRpbmdzL3JlZGlzLm1k..993d60ee27433337d349656f3c19f551c32bedc4_ZG9jL3NldHRpbmdzL3JlZGlzLm1k 100644 --- a/doc/settings/redis.md +++ b/doc/settings/redis.md @@ -104,6 +104,16 @@ redis['tcp_keepalive'] = "300" ``` +## Announce ip from hostname + +Currently the only way to enable hostnames in Redis is by setting `redis['announce_ip']`. However, +this would need to be set uniquely per Redis instance. `announce_ip_from_hostname` is a boolean that allows us to turn this on or off. +It fetches the hostname dynamically, inferring the hostname from `hostname -f` command. + +```ruby +redis['announce_ip_from_hostname'] = true +``` + ## Setting the Redis Cache instance as an LRU Using multiple Redis instances allows you to configure Redis as a [Least diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..993d60ee27433337d349656f3c19f551c32bedc4_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644 --- a/files/gitlab-config-template/gitlab.rb.template +++ b/files/gitlab-config-template/gitlab.rb.template @@ -1334,6 +1334,7 @@ ####! Docs: https://redis.io/topics/replication#configuring-replication-in-docker-and-nat # redis['announce_ip'] = nil # redis['announce_port'] = nil +# redis['announce_ip_from_hostname'] = false ####! **Master password should have the same value defined in ####! redis['password'] to enable the instance to transition to/from diff --git a/files/gitlab-cookbooks/gitlab-ee/libraries/sentinel_helper.rb b/files/gitlab-cookbooks/gitlab-ee/libraries/sentinel_helper.rb index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWItZWUvbGlicmFyaWVzL3NlbnRpbmVsX2hlbHBlci5yYg==..993d60ee27433337d349656f3c19f551c32bedc4_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWItZWUvbGlicmFyaWVzL3NlbnRpbmVsX2hlbHBlci5yYg== 100644 --- a/files/gitlab-cookbooks/gitlab-ee/libraries/sentinel_helper.rb +++ b/files/gitlab-cookbooks/gitlab-ee/libraries/sentinel_helper.rb @@ -16,13 +16,14 @@ def use_hostnames # Detect if user is overriding what we want to calculate here - if sentinel['use_hostnames'].nil? - # Match on IP addresses, if an IP address is detected, we will NOT use hostnames - !!(sentinel['announce_ip'].nil? || sentinel['announce_ip'] =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex])) ? 'no' : 'yes' - else - # Leverage user override - sentinel['use_hostnames'] ? 'yes' : 'no' - end + return sentinel['use_hostnames'] ? 'yes' : 'no' unless sentinel['use_hostnames'].nil? + + return 'yes' if redis['announce_ip_from_hostname'] + + # Enable hostnames if a non-IP address value is provided in announce_ip + return 'yes' if sentinel['announce_ip'] && !Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex]).match(sentinel['announce_ip']) + + 'no' end def running_version @@ -79,6 +80,10 @@ @node['gitlab']['sentinel'] end + def redis + @node['redis'] + end + # Load from local JSON file def load_from_file Chef::JSONCompat.from_json(File.read(JSON_FILE)) if File.exist?(JSON_FILE) diff --git a/files/gitlab-cookbooks/gitlab/libraries/redis_helper.rb b/files/gitlab-cookbooks/gitlab/libraries/redis_helper.rb index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL3JlZGlzX2hlbHBlci5yYg==..993d60ee27433337d349656f3c19f551c32bedc4_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL3JlZGlzX2hlbHBlci5yYg== 100644 --- a/files/gitlab-cookbooks/gitlab/libraries/redis_helper.rb +++ b/files/gitlab-cookbooks/gitlab/libraries/redis_helper.rb @@ -10,6 +10,8 @@ gitlab_rails_config = @node['gitlab']['gitlab-rails'] redis_config = @node['redis'] + raise 'Redis announce_ip and announce_ip_from_hostname are mutually exclusive, please unset one of them' if redis_config['announce_ip'] && redis_config['announce_ip_from_hostname'] + params = if RedisHelper::Checks.has_sentinels? && support_sentinel_groupname [redis_config['master_name'], redis_config['master_port'], redis_config['master_password']] else diff --git a/files/gitlab-cookbooks/redis/attributes/attributes.rb b/files/gitlab-cookbooks/redis/attributes/attributes.rb index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy9hdHRyaWJ1dGVzL2F0dHJpYnV0ZXMucmI=..993d60ee27433337d349656f3c19f551c32bedc4_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy9hdHRyaWJ1dGVzL2F0dHJpYnV0ZXMucmI= 100644 --- a/files/gitlab-cookbooks/redis/attributes/attributes.rb +++ b/files/gitlab-cookbooks/redis/attributes/attributes.rb @@ -63,3 +63,4 @@ #### default['redis']['announce_ip'] = nil default['redis']['announce_port'] = nil +default['redis']['announce_ip_from_hostname'] = false diff --git a/files/gitlab-cookbooks/redis/templates/default/sv-redis-run.erb b/files/gitlab-cookbooks/redis/templates/default/sv-redis-run.erb index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy90ZW1wbGF0ZXMvZGVmYXVsdC9zdi1yZWRpcy1ydW4uZXJi..993d60ee27433337d349656f3c19f551c32bedc4_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy90ZW1wbGF0ZXMvZGVmYXVsdC9zdi1yZWRpcy1ydW4uZXJi 100644 --- a/files/gitlab-cookbooks/redis/templates/default/sv-redis-run.erb +++ b/files/gitlab-cookbooks/redis/templates/default/sv-redis-run.erb @@ -2,4 +2,9 @@ exec 2>&1 <%= render('mount_point_check.erb', cookbook: 'gitlab') %> umask 077 -exec chpst -P -U <%= node['redis']['username'] %>:<%= node['redis']['group'] %> -u <%= node['redis']['username'] %>:<%= node['redis']['group'] %> /opt/gitlab/embedded/bin/redis-server <%= File.join(node[@options[:service]]['dir'], "redis.conf") %> +exec chpst -P \ + -U <%= node['redis']['username'] %>:<%= node['redis']['group'] %> \ + -u <%= node['redis']['username'] %>:<%= node['redis']['group'] %> \ + /opt/gitlab/embedded/bin/redis-server \ + <%= File.join(node[@options[:service]]['dir'], "redis.conf") %> \ + <% if node['redis']['announce_ip_from_hostname'] %>--replica-announce-ip "$(hostname -f)"<% end %> diff --git a/spec/chef/cookbooks/gitlab-ee/recipes/sentinel_spec.rb b/spec/chef/cookbooks/gitlab-ee/recipes/sentinel_spec.rb index 680fea497f6bfdbf90d7aa93d2a7397ca7db8baa_c3BlYy9jaGVmL2Nvb2tib29rcy9naXRsYWItZWUvcmVjaXBlcy9zZW50aW5lbF9zcGVjLnJi..993d60ee27433337d349656f3c19f551c32bedc4_c3BlYy9jaGVmL2Nvb2tib29rcy9naXRsYWItZWUvcmVjaXBlcy9zZW50aW5lbF9zcGVjLnJi 100644 --- a/spec/chef/cookbooks/gitlab-ee/recipes/sentinel_spec.rb +++ b/spec/chef/cookbooks/gitlab-ee/recipes/sentinel_spec.rb @@ -1,8 +1,8 @@ require 'chef_helper' RSpec.describe 'gitlab::redis' do - let(:chef_run) { ChefSpec::SoloRunner.new(step_into: %w(sentinel_service runit_service)).converge('gitlab-ee::default') } + let(:chef_run) { ChefSpec::SoloRunner.new(step_into: %w(redis_service sentinel_service runit_service)).converge('gitlab-ee::default') } let(:redis_master_ip) { '1.1.1.1' } let(:redis_announce_ip) { '10.10.10.10' } let(:redis_master_password) { 'blahblahblah' } let(:sentinel_conf) { '/var/opt/gitlab/sentinel/sentinel.conf' } @@ -5,7 +5,8 @@ let(:redis_master_ip) { '1.1.1.1' } let(:redis_announce_ip) { '10.10.10.10' } let(:redis_master_password) { 'blahblahblah' } let(:sentinel_conf) { '/var/opt/gitlab/sentinel/sentinel.conf' } + let(:redis_sv_run) { '/opt/gitlab/sv/redis/run' } before do allow(Gitlab).to receive(:[]).and_call_original @@ -33,6 +34,7 @@ before do stub_gitlab_rb( redis: { + enable: true, master_ip: redis_master_ip, announce_ip: redis_announce_ip, master_password: redis_master_password @@ -62,6 +64,12 @@ } end + it 'renders redis service definition without --replica-announce-ip' do + expect(chef_run).to render_file(redis_sv_run).with_content { |content| + expect(content).not_to match(%r{--replica-announce-ip "\$\(hostname -f\)"}) + } + end + it_behaves_like 'enabled runit service', 'sentinel', 'root', 'root' context 'user overrides sentinel_use_hostnames' do @@ -80,6 +88,29 @@ } end end + + context 'user enables announce_ip_from_hostname' do + before do + stub_gitlab_rb( + redis: { + enable: true, + master_ip: redis_master_ip, + announce_ip_from_hostname: true, + master_password: redis_master_password + }) + end + + it 'uses hostnames' do + expect(chef_run).to render_file(sentinel_conf).with_content { |content| + expect(content).to match(%r{SENTINEL resolve-hostnames yes}) + expect(content).to match(%r{SENTINEL announce-hostnames yes}) + } + + expect(chef_run).to render_file(redis_sv_run).with_content { |content| + expect(content).to match(%r{--replica-announce-ip "\$\(hostname -f\)"}) + } + end + end end context 'user specified values' do