2017-11-25

Integration with etcd (Extension Module)

Tamaya Etcd is an extension module. Refer to the extensions documentation for further details.

What functionality this module provides ?

Tamaya Etcd provides different artifacts which allows using etcd as a configuration backend. Basically the module adds a read-only property source (EtcdPropertySource). If the tamaya-mutable-config extension is loaded it is alos possible to write configuration changes to etcd using MutableConfiguration.

Compatibility

The module is based on Java 7, so it will not run on Java 7 and beyond.

Installation

To use etcd as a configuration backend you only must add the corresponding dependency to your module:

<dependency>
  <groupId>org.apache.tamaya.ext</groupId>
  <artifactId>tamaya-etcd</artifactId>
  <version>{tamaya_version}</version>
</dependency>

The Extensions Provided

Tamaya’s etcd integration provides basically the following artifacts:

  • The org.apache.tamaya.etcd.EtcdAccessor can be configured with a an url targeting an etcd server’s REST endpoint root. The accessor basically provides a simple Java API for communicating with the etcd server. The accessor hereby allows reading of single properties, or whole subtrees. Also the basic non atomic write methods are implemented.

  • The org.apache.tamaya.etcd.EtcdPropertySource is a PropertySource with a default ordinal of 100 and the name 'etcd', which is automatically registered.

  • If the tamaya-mutable-config module is loaded it is possible to write property values back into the etcd cluster, by accessing a MutableConfiguration using the URI config:etcd.

The EtcdAccessor

The accessor implements the basic read and write API for communicating with an etcd server. Hereby the accessor also provides etcd specific data such as createdIndex, modifiedIndex, ttl in the Map returned. Hereby the concept of etcd is used where keys starting with an '_' represent meta-configuration that will be hidden from the overall properties map, being only directly/explicitly accessible:

public class EtcdAccessor {

    /**
     * Creates a new instance with the basic access url.
     * @param server server url, e.g. {@code http://127.0.0.1:4001}.
     * @throws MalformedURLException
     */
    public EtcdAccessor(String server) throws MalformedURLException;

    /**
     * Get the etcd server version.
     * @return the etcd server version, never null.
     */
    public String getVersion();

    /**
     * Ask etcd for s aingle key, value pair. Hereby the response returned from etcd:
     * <pre>
     *     key=value
     *     _key.source=[etcd]http://127.0.0.1:4001
     *     _key.createdIndex=12
     *     _key.modifiedIndex=34    // optional
     *     _key.ttl=300             // optional
     *     _key.expiration=...      // optional
     * </pre>
     * @param key the requested key
     * @return the mapped result, including meta-entries.
     */
    public Map<String,String> get(String key);

    /**
     * Creates/updates an entry in etcd without any ttl set.
     * The response is as follows:
     * <pre>
     *     key=value
     *     _key.source=[etcd]http://127.0.0.1:4001
     *     _key.createdIndex=12
     *     _key.modifiedIndex=34             // optional
     *     _key.prevNode.createdIndex=12     // optional
     *     _key.prevNode.modifiedIndex=34    // optional
     * </pre>
     * @param key the property key, not null
     * @param value the value to be set
     * @return the result map as described above.
     */
    public Map<String,String> set(String key, String value);

    /**
     * Creates/updates an entry in etcd. The response is as follows:
     * <pre>
     *     key=value
     *     _key.source=[etcd]http://127.0.0.1:4001
     *     _key.createdIndex=12
     *     _key.modifiedIndex=34             // optional
     *     _key.ttl=300                      // optional
     *     _key.expiry=...                   // optional
     *     _key.prevNode.createdIndex=12     // optional
     *     _key.prevNode.modifiedIndex=34    // optional
     *     _key.prevNode.ttl=300             // optional
     *     _key.prevNode.expiration=...      // optional
     * </pre>
     * @param key the property key, not null
     * @param value the value to be set
     * @param ttlSeconds the ttl in seconds (optional)
     * @return the result map as described above.
     */
    public Map<String,String> set(String key, String value, Integer ttlSeconds);


    /**
     * Deletes a given key. The response is as follows:
     * <pre>
     *     _key.source=[etcd]http://127.0.0.1:4001
     *     _key.createdIndex=12
     *     _key.modifiedIndex=34
     *     _key.ttl=300                       // optional
     *     _key.expiry=...                    // optional
     *     _key.prevNode.createdIndex=12      // optional
     *     _key.prevNode.modifiedIndex=34     // optional
     *     _key.prevNode.ttl=300              // optional
     *     _key.prevNode.expiration=...       // optional
     *     _key.prevNode.value=...            // optional
     * </pre>
     * @param key the key to be deleted.
     * @return the response mpas as described above.
     */
    public Map<String,String> delete(String key);


    /**
     * Access regular Tamaya properties map as follows:
     * <pre>
     *    key1=myvalue
     *     _key1.source=[etcd]http://127.0.0.1:4001
     *     _key1.createdIndex=12
     *     _key1.modifiedIndex=34          // optional
     *     _key1.ttl=300                   // optional
     *     _key1.expiration=...            // optional
     *
     *      key2=myvaluexxx
     *     _key2.source=[etcd]http://127.0.0.1:4001
     *     _key2.createdIndex=12
     *
     *      key3=val3
     *     _key3.source=[etcd]http://127.0.0.1:4001
     *     _key3.createdIndex=12
     *     _key3.modifiedIndex=2
     * </pre>
     */
    public Map<String,String> getProperties(String directory, boolean recursive);

}

The EtcdPropertySource

The EtcdPropertySource is automatically registered and allows to configure the etcd servers to be used. This enables to use e.g. in Docker environments the docker environment configuration mechanisms to configure Tamaya running in microservice containers to connect with the according etcd cluster:

  • The property source reads the tamaya.etcd.server.urls system and environment property to evaluate possible etcd servers (comma separated), which can be connected to. On error the API just performs a Round-Robin through the list of configured servers. Without any configuration http://127.0.0.1:4001 is used. If no connection to any etcd server can be established a warning will be logged, but deployment will not fail.

  • Additionally also the accessor allows to configure the socket/connection timeouts by setting tamaya.etcd.timeout in seconds either as system or environment property.

  • The EtcdPropertySource finally also allows the values read from the etcd cluster to be mapped to prefixed context. This can be activated by setting the -Dtamaya.etcd.prefix=<PREFIX> system property. E.g. when the prefix is set to cluster-config. a etcd key of host:known/all is mapped to cluster-config.host:known/all.