Skip to content
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

instance_uri() method for config module #4120

Closed
Tracked by #4294
TarantoolBot opened this issue Apr 2, 2024 · 1 comment · Fixed by #4331
Closed
Tracked by #4294

instance_uri() method for config module #4120

TarantoolBot opened this issue Apr 2, 2024 · 1 comment · Fixed by #4331
Assignees

Comments

@TarantoolBot
Copy link
Collaborator

TarantoolBot commented Apr 2, 2024

Related dev. issue(s): tarantool/tarantool#9842

Product: Tarantool
Since: 3.1
Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/config/
SME: @ ImeevMA

Details

The configuration module's instance_uri() method returns the URI of
the instance that is used to create a replicaset or sharding cluster.
This method takes two arguments:

  1. peer or null to return the URI that is used to create the
    replicaset, or sharding to return the URI that is used to create
    the sharding cluster;
  2. options, which only support options.instance, to specify the
    instance whose URI should be returned; by default, the URI of the
    instance on which the function is executed is returned.
    Requested by @ ImeevMA in tarantool/tarantool@1826ca7.
@Totktonada
Copy link
Member

I would like to define a behavior of the method in a more formal way.

API

local config = require('config')

config:instance_uri([uri_type[, opts]])

Synopsis

An advertise URI of the given instance.

The function returns an URI suitable to connect to the given instance from within the cluster1.

Arguments

  1. uri_type: one-of('peer', 'sharding')

  2. opts: a table of options

    opts.instance: <instance name>2

Return value

Returns an URI in the following format (or nil).

{
    login = <string>,
    password = <string>,
    uri = <host:port>,
    params = {
        transport = one-of('plain', 'ssl'),
        ssl_ca_file = <string>,
        ssl_cert_file = <string>,
        ssl_ciphers = <string>,
        ssl_key_file = <string>,
        ssl_password = <string>,
        ssl_password_file = <string>,
    },
}

uri is always present, all the other fields are optional.

If the URI can't be determied, nil is returned.

This format is suitable to directly pass into net_box.connect().

Description

The idea of the function is to pick up information from iproto.advertise.<uri_type> and saturate it if it is incomplete or missed at all.

flowchart TD
    lookup_uri{"iproto.advertise.&lt;uri_type&gt;.uri"}
    set_advertise_uri_params["res.uri = iproto.advertise.&lt;uri_type&gt;.uri\nres.params = iproto.advertise.&lt;uri_type&gt;.params"]
    set_listen_uri_params["res.uri = iproto.listen[i].uri\nres.params = iproto.listen[i].params"]
    i_0[i = 0]
    incr[i = i + 1]
    has_next{"i < len(iproto.listen)"}
    set_nil["res = nil"]
    is_not_suitable{"parse(iproto.listen[i]).ipv4 == '0.0.0.0' ||\nparse(iproto.listen[i]).ipv6 == '::' ||\nparse(iproto.listen[i]).service == '0'"}
    has_login{"iproto.advertise.&lt;uri_type&gt;.login"}
    set_login[res.login = iproto.advertise.&lt;uri_type&gt;.login]
    has_password{"iproto.advertise.&lt;uri_type&gt;.password"}
    set_password["res.password = iproto.advertise.&lt;uri_type&gt;.password"]
    dont_need_password{"res.login == 'guest'"}
    has_credentials_password{"credentials.users.&lt;res.login&gt;.password"}
    set_credentials_password["res.password = credentials.users.&lt;res.login&gt;.password"]
    return_0((return))
    return_1((return))
    return_2((return))
    return_3((return))
    return_4((return))
    return_5((return))

    style set_advertise_uri_params text-align:left
    style set_listen_uri_params text-align:left
    style is_not_suitable text-align:left

    lookup_uri -- exists --> set_advertise_uri_params
    lookup_uri -- missed --> i_0
    i_0 --> has_next
    has_next -- yes --> is_not_suitable
    is_not_suitable -- no --> set_listen_uri_params
    is_not_suitable -- yes --> incr
    incr --> has_next

    has_next -- no --> set_nil
    set_nil --> return_0

    set_advertise_uri_params --> has_login
    set_listen_uri_params --> has_login

    has_login -- missed --> return_1
    has_login -- exists --> set_login
    set_login --> has_password

    has_password -- exists --> set_password
    has_password -- missed --> dont_need_password

    set_password --> return_2

    dont_need_password -- yes --> return_3
    dont_need_password -- no --> has_credentials_password

    has_credentials_password -- exists --> set_credentials_password
    has_credentials_password -- missed --> return_4

    set_credentials_password --> return_5
Loading

Let's define res as the resulting URI: a table where login, password, uri, params fields may exist.

If uri is present in iproto.advertise.<uri_type>, uri and params are copied to res.

If uri is not present, uri and params are looked up in iproto.listen. The lookup is performed as follows: a first URI that is suitable to connect is chosen. An URI is suitable to connect if the host part is not 0.0.0.0 and not :: and the port is not zero.

If the steps above can't find a suitable URI, res is nil. Otherwise, res.uri and res.params are defined.

If iproto.advertise.<uri_type> has a login field, it is copied to res. Otherwise, res.login doesn't exist1.

If iproto.advertise.<uri_type>.login exists and it is not guest and iproto.advertise.<uri_type> has a password field, it is copied to res. Otherwise, the password is looked up in credentials.users.<login>.password in the configuration. If this configuration field exists, it is set as res.password. Otherwise, res.password doesn't exist.

Footnotes

  1. Use config:get('iproto.advertise.client', opts) for connecting from outside of the given cluster. 2

  2. opts.instance works in the same way as the same named config:get() option. The method takes TT_* environment variables into account if opts.instance is omitted, but ignores them if it is provided. See gh-9824 for details and a discussion.

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

Successfully merging a pull request may close this issue.

3 participants