Skip to content

Sentinels: Accept options to connect to master #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

jlledom
Copy link
Contributor

@jlledom jlledom commented Jun 5, 2025

I tried to use SentinelClient on my project and found I couldn't connect to Sentinels + TLS or ACL. The reason is there no way to provide connection options for the master, only for the sentinels. So sentinels can be protected with TLS and ACL and async-reds will connect to them, but after resolving master, SentinelClient will only connect to master if it is not protected by TLS nor ACL.

I wrote this script to test the changes:

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  #gem 'async-redis'
  gem 'async-redis', git: 'https://github.com/jlledom/async-redis', branch: 'jlledom-sentinels-tls-acl'
end

def main
  Async do
    sentinels = [{ host: 'localhost', port: 56380 },
                 { host: 'localhost', port: 56381 },
                 { host: 'localhost', port: 56382 }]

    ssl_params = {
      ca_file: '/path/to/ca-root-cert.pem',
    }
    ssl_context = OpenSSL::SSL::SSLContext.new.tap do |context|
      context.set_params(ssl_params)
    end

    database = '6'
    credentials = %w[username password]
    endpoint_options = {database:, credentials:, ssl_context: }.compact

    sentinel_credentials = %w[sentinel_username sentinel_password]
    master_name = 'redis-master'
    role = :master

    endpoints = sentinels.map do |sentinel|
      scheme = ssl_context ? 'rediss' : 'redis'
      host = sentinel[:host]
      port = sentinel[:port]
      sentinel_uri = URI::Generic.build(scheme:, host:, port:)
      Async::Redis::Endpoint.new(sentinel_uri, nil, credentials: sentinel_credentials, ssl_context:)
    end
    client = Async::Redis::SentinelClient.new(endpoints, master_name:, master_options: endpoint_options, role:)

    while true
      begin
        sleep 1
        result = client.ping 'test'
        puts result
      rescue StandardError => e
        puts e.message
        retry
      end
    end
  end
end

main

Types of Changes

  • Bug fix.

Contribution

I didn't add tests because those must involve much more than just writing the tests. It would require creating a new docker compose file, new certificates, config files, etc.

@role = role
@protocol = protocol
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the @protocol instance variable because, AFAIK, it is only used to connect to the master, and at this point we still don't know which one will be.

Comment on lines +31 to +32
@ssl = !!master_options&.key?(:ssl_context)
@scheme = "redis#{@ssl ? 's' : ''}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't kinda like this, any ideas?

@@ -116,7 +119,6 @@ def resolve_slave
protected

def assign_default_tags(tags)
tags[:protocol] = @protocol.to_s
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what is this for. I hope I'm not breaking anything.

@protocol.client(stream)

endpoint.protocol.client(stream)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use the endpoint protocol to connect to the endpoint, I think this is more correct and removes the need for the instance variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant