The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Connector::Multi

DESCRIPTION

This class implements a Connector that is capable of dealing with dynamically configured Connector implementations and symlinks.

The underlying concept is that there is a primary (i.e.: boot) configuration source that Multi accesses for get() requests. If the request returns a reference to a SCALAR, Multi interprets this as a symbolic link. The content of the link contains an alias and a target key.

Example

In this example, we will be using a YAML configuration file that is accessed via the connector Connector::Proxy::YAML.

From the programmer's view, the configuration should look something like this:

  smartcards:
    tokens:
        token_1:
            status: ACTIVATED
        token_2:
            status: DEACTIVATED
    owners:
        joe:
            tokenid: token_1
        bob:
            tokenid: token_2

In the above example, calling get('smartcards.tokens.token_1.status') returns the string 'ACTIVATED'.

To have the data fetched from an LDAP server, we can redirect the 'smartcards.tokens' key to the LDAP connector using '@' to indicate symlinks. Our primary configuration source for both tokens and owners would contain the following entries:

  smartcards:
    @tokens: connector:connectors.ldap-query-token
    @owners: connector:connectors.ldap-query-owners

With the symlink now in the key, Multi must walk down each level itself and handle the symlink. When 'smartcards.tokens' is reached, it reads the contents of the symlink, which is an alias to a connector 'ldap-query-token'. The connector configuration is in the 'connectors' namespace of our primary data source.

  connectors:
    ldap-query-tokens:
        class: Connector::Proxy::Net::LDAP
        basedn: ou=smartcards,dc=example,dc=org
        server:
            uri: ldaps://example.org
            bind_dn: uid=user,ou=Directory Users,dc=example,dc=org
            password: secret

  connectors:
    ldap-query-owners:
        class: Connector::Proxy::Net::LDAP
        basedn: ou=people,dc=example,dc=org
        server:
            uri: ldaps://example.org
            bind_dn: uid=user,ou=Directory Users,dc=example,dc=org
            password: secret

NOTE: The following is not implemented yet.

Having two queries with duplicate server information could also be simplified. In this case, we define that the server information is found when the connector accesses 'connectors.ldap-query-token.server.<param>'. The resulting LDAP configuration would then be:

  connectors:
    ldap-query-token:
        class: Connector::Proxy::Net::LDAP
        basedn: ou=smartcards,dc=example,dc=org
        @ldap-server: redirect:connectors.ldap-example-org
    ldap-query-owners:
        class: Connector::Proxy::Net::LDAP
        basedn: ou=people,dc=example,dc=org
        @ldap-server: redirect:connectors.ldap-example-org
    ldap-example-org:
        uri: ldaps://example.org
        bind_dn: uid=user,ou=Directory Users,dc=example,dc=org
        password: secret

The alias 'connectors.ldap-example-org' contains the definition needed by the LDAP connector. In this case, we don't need a special connector object. Instead, all we need is a simple redirect that allows two different entries (in this case, the other two connectors) to share a common entry in the tree.

SYNOPSIS

The parameter BASECONNECTOR may either be a class instance or the name of the class, in which case the additional arguments (e.g.: LOCATION) are passed to the base connector.

  use Connector::Proxy::Config::Versioned;
  use Connector::Multi;

  my $base = Connector::Proxy::Config::Versioned->new({
    LOCATION => $path_to_internal_config_git_repo,
  });

  my $multi = Connector::Multi->new( {
    BASECONNECTOR => $base,
  });

  my $tok = $multi->get('smartcard.owners.bob.tokenid');

or...

  use Connector::Multi;

  my $multi = Connector::Multi->new( {
    BASECONNECTOR => 'Connector::Proxy::Config::Versioned',
    LOCATION => $path_to_internal_config_git_repo,
  });

  my $tok = $multi->get('smartcard.owners.bob.tokenid');

You can also pass the path as an arrayref, where each element can be a path itself

  my $tok = $multi->get( [ 'smartcard.owners', 'bob.tokenid' ]);

OPTIONS

When creating a new instance, the new() constructor accepts the following options:

BASECONNECTOR

This is a reference to the Connector instance that Connector::Multi uses at the base of all get() requests.

Supported methods

get, get_list, get_size, get_hash, get_keys, set, get_meta Those are routed to the appropriate connector.

get_connector Return the instance of the connector at this node

get_wrapper Return a wrapper around this node. This is like setting a prefix for all subsequent queries.

   my $wrapper = $conn->get_wrapper('test.node');
   $val = $wrapper->get('foo');

Is the same as $val = $conn->get_wrapper('test.node.foo');