{"id":16726321,"url":"https://github.com/brunobonacci/synapse","last_synced_at":"2025-10-12T17:07:09.650Z","repository":{"id":62431756,"uuid":"51224270","full_name":"BrunoBonacci/synapse","owner":"BrunoBonacci","description":"The smart way to link containers","archived":false,"fork":false,"pushed_at":"2019-06-12T22:40:23.000Z","size":83,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-03-25T21:45:11.748Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BrunoBonacci.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-06T22:03:48.000Z","updated_at":"2021-10-27T08:32:13.000Z","dependencies_parsed_at":"2022-11-01T21:00:43.988Z","dependency_job_id":null,"html_url":"https://github.com/BrunoBonacci/synapse","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrunoBonacci%2Fsynapse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrunoBonacci%2Fsynapse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrunoBonacci%2Fsynapse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrunoBonacci%2Fsynapse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BrunoBonacci","download_url":"https://codeload.github.com/BrunoBonacci/synapse/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248199088,"owners_count":21063641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-12T22:52:51.677Z","updated_at":"2025-10-12T17:07:04.630Z","avatar_url":"https://github.com/BrunoBonacci.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# synapse\n\nSynapse is the smart way to connect and configure docker containers.\nIt uses a number of strategies to retrieve configuration and discover\ndependencies such as: environment variables, docker standard variables\n(to come: Kubernetes discovery API, Consul discovery API, Consul\nconfiguration API, etcd configuration API).\n\n## Download\n\nIt comes in two forms: a command line tool, or a Clojure library:\n\nDownload latest command line tool release here:\n\n  - [synapse for Linux x86_64](https://github.com/BrunoBonacci/synapse/releases/download/0.4.0/synapse-Linux-x86_64)\n  - [synapse for OS X x86_64](https://github.com/BrunoBonacci/synapse/releases/download/0.4.0/synapse-Darwin-x86_64)\n  - [synapse for Java8 (executable jar)](https://github.com/BrunoBonacci/synapse/releases/download/0.4.0/synapse)\n\nDownload the latest library version here:\n\n  - [synapse as Clojure library](https://clojars.org/com.brunobonacci/synapse)\n\n## Installation\n\n  * Installation via Homebrew\n  ``` bash\n  brew tap BrunoBonacci/lazy-tools\n  brew install synapse\n  ```\n\n  * Install command line tool (Native binary for Mac-OSX and Linux)\n  ``` bash\n  mkdir -p ~/bin\n  wget https://github.com/BrunoBonacci/synapse/releases/download/0.4.0/synapse-$(uname -s)-$(uname -m) -O ~/bin/synapse\n  chmod +x ~/bin/synapse\n  export PATH=~/bin:$PATH\n  ```\n\n  * Install command line tool (for Windows and other platforms, requires Java JRE)\n  ``` bash\n  mkdir -p ~/bin\n  wget https://github.com/BrunoBonacci/synapse/releases/download/0.4.0/synapse -O ~/bin/synapse\n  chmod +x ~/bin/synapse\n  export PATH=~/bin:$PATH\n  ```\n\n## Usage\n\nAt its simplest `synapse` takes environment variables and replaces them\ninto configuration files, but there is more.\nYou can create your configuration files and put resolvable tags in\nthe place where you expect values passed down to the container.\nSynapse will then replace the tag (or placeholder) with the actual value.\n\nLet's see the anatomy of a resolvable tag:\n\n```\n               target pattern\n     resolver       |           delimiter\n         |          |           |\n      %%docker\u003e\u003ezookeeper.*:2181%%\n       |      |              |\ndelimiter     |            port\n           single or    (optional)\n            multiple\n\n```\n\n### Cheatsheet\n\n**TL;DR** A quick example based list of available resolvable tags.\n\n```\n  # Environment variable are replace with their value\n  %%HOME%%                   =\u003e /home/ubuntu\n  %%env\u003eHOME%%               =\u003e /home/ubuntu\n\n  # A default value can be given with a double pipe (||)\n  %%HOME||/home/user1%%      =\u003e /home/ubuntu\n  %%LOGS_DIR%%               =\u003e %%LOGS_DIR%%\n  %%LOGS_DIR||/var/logs%%    =\u003e /var/logs\n\n  # When multiple environment are expected use a pattern\n  # together with a double angle bracket `\u003e\u003e` instead\n  # instead of the single angle bracket `\u003e`\n  %%ALLOWED_IP1%%            =\u003e 172.17.0.21\n  %%ALLOWED_IP2%%            =\u003e 172.17.1.2\n  %%ALLOWED_IP3%%            =\u003e 172.17.3.45\n  %%env\u003e\u003eALLOWED_IP.*%%      =\u003e 172.17.0.21,172.17.3.45,172.17.1.2\n  %%env\u003eALLOWED_IP.*%%       =\u003e 172.17.0.21\n\n  # When translating from a number of environment variables to\n  # properties with a common prefix you can use the `prefix` resolver\n  # it will find all the environment variable with this prefix and\n  # turn them into properties with the corresponding value.\n  # For example, if you have the following environment variables\n  # CONF_DATABASE_HOST=db.dev.local\n  # CONF_DATABASE_PORT=1234\n  # they can be automatically replaced into their corresponding\n  # properties with:\n  %%prefix\u003eCONF_%%           =\u003e database.host=db.dev.local\n                                database.port=1234\n\n  # you can control the case and the separator with the following options\n  %%prefix[case=camel,sep=]\u003eCONF_%%\n                             =\u003e databaseHost=db.dev.local\n                                databasePort=1234\n\n  # for the odd cases you can preserve the case of the variables\n  # CONF_DataBase_Host=db.dev.local\n  # CONF_DataBase_Port=1234\n  %%prefix[case=preserve]\u003eCONF_%%\n                             =\u003e DataBase_Host=db.dev.local\n                                DataBase_Host=1234\n\n\n  # When resolving docker links use the docker resolver\n  %%docker\u003edb:3306%%         =\u003e 172.17.12.21:12321\n  %%\u003edb:3306%%               =\u003e 172.17.12.21:12321\n  %%docker\u003eels1:9200%%       =\u003e 172.17.15.10:24123\n  %%\u003eels1:9200%%             =\u003e 172.17.15.10:24123\n  %%\u003e\u003eels.*:9200%%           =\u003e 172.17.15.20:12433,172.17.15.10:24123,172.17.15.30:9413\n\n  # ELS exposes two ports 9200, 9300, if not set the lowest is choosen\n  %%\u003e\u003eels.*%%                =\u003e 172.17.15.20:12433,172.17.15.10:24123,172.17.15.30:9413\n\n  # if you want only one address but multiple are matching\n  # the first is lexicographic order is returned.\n  %%\u003eels.*:9200%%            =\u003e 172.17.15.10:24123\n\n  # defaults works in the same ways\n  %%\u003esmtp:25||localhost:25%% =\u003e localhost:25\n\n  # you can resolve address and ports separately\n  %%[addr]\u003edb:3306%%         =\u003e 172.17.12.21\n  %%[port]\u003edb:3306%%         =\u003e 12321\n\n  # you can use also with multiple targets\n  %%[addr]\u003e\u003eels.*:9200%%     =\u003e 172.17.15.20,172.17.15.10,172.17.15.30\n\n  # you can customize the separtor with\n  %%[addr,sep=;]\u003e\u003eels.*:9200%% =\u003e 172.17.15.20;172.17.15.10;172.17.15.30\n```\n\n### Basics\n\nHere some examples of resolvable tags (more to come):\n\n\n* `%%HOME%%`, `%%env\u003eHOME%%`, `%%DATA_DIR%%`, `%%data_dir%%`\n\n  It will look for a matching environment variable,\n  when found it will replace the tag with its value.\n  the var name/pattern is **case insensitive**.\n\n* `%%env\u003e\u003eSERVICE.*%%`\n  A double angle bracket (`\u003e\u003e`) means that you expect more\n  than one result. It will look for environment variables\n  like: `$SERVICE1`, `$SERVICE2`, `$SERVICE3` (matching\n  `SERVICE.*` regex) and replace the tag with the values\n  as a comma-separated list.\n\n* `%%docker\u003ezookeeper%%`\n\n  It will look for Docker's standard environment variables\n  to link the container. For example it in this case it will\n  look for: `$ZOOKEEPER_PORT_2181_TCP_ADDR`,\n  `$ZOOKEEPER_PORT_2181_TCP_PORT` and `$ZOOKEEPER_PORT_2181_TCP`\n  The docker resolution is the most commonly used so you can\n  omit the `docker` resolver name.\n\n* `%%\u003ezookeeper%%`\n\n  When the port is not specified it will look for all available\n  port names and take the lowest. A service might have more\n  than one service port (such as admin port or peers port)\n  but typically the client port is the lowest one.\n\n* `%%\u003ezookeeper:2181%%`\n\n  Otherwise you can specify the port you wish. This will be\n  resolved and replaced with the actual container's port.\n\n* `%%\u003e\u003ezookeeper.*:2181%%`\n\n  If you expect more than one container with a given name\n  then you can specify a pattern and add a double angle\n  bracket (`\u003e\u003e`). In this case it will look for all zookeeper\n  containers and replace the tag with a comma-separated list.\n\n\n### Default values\n\n* `%%DATA_DIR||//mnt/data%%`  or  `%%env\u003eDATA_DIR||//mnt/data%%`, `%%\u003e\u003ezookeeper.*:2181||10.10.10.10:1221%%`\n\n  You can provide a default value which will be used in case\n  no matching candidate env vars are found. Just add `||`\n  (double pipe) followed by the default value. The default\n  value can be also empty which will resolve to an empty\n  string (eg: `%%SOME_VAR||%%`). This it can be useful\n  in cases when you want to resolve a value if given\n  but not fail it isn't set in the environment.\n\n\n### Partial resolution and other options\n\n* `%%[addr]\u003ezookeeper.*:2181%%` (=\u003e `172.17.0.2`) or `%%[port]\u003ezookeeper:2181%%` (=\u003e `34765`)\n\n  In some cases it might be useful to get just the host address or\n  just the port number, for example when the configuration settings\n  require two separate entries. In such case just add `[addr]` or\n  `[port]` before the single or double angle bracket and the\n  resolver will emit just the part you are interested in.\n  Omitting this option is the same as `[addr,port]`\n\n* `%%[sep=;]\u003e\u003ezookeeper.*:2181%%`\n\n  You can customize the separator by adding `sep=` followed by the\n  separator you wish to add. It can be empty, a single character or a\n  string. `\\n` and `\\t` will be unescaped while the comma (`,`)\n  is not supported as it is the default separator.\n\n\n### The resolvers\n\nThe resolver decides how the rest of the tag is interpreted.\n\n#### `env` resolver\n\nThe simplest resolver is the `env` resolver which takes the target and\ntries to find a matching environment variable to resolve.\n\nFor example the tag `%%env\u003eDATA_DIR%%` will be replaced with the\ncontent of the environment variable `$DATA_DIR` if it is defined. If\nthe environment variable is not found then the tag will be left\nunchanged and an error will be reported.\n\nWhen trying to resolve an environment variable directly the `env\u003e`\npart can be omitted so the previous tag can be written as\n`%%DATA_DIR%%`.\n\n\n#### `prefix` resolver\n\nThere are many cases where the application you trying to configure\nhas a large number of properties which can be configured and you\nneed to provide the same capability via environment variables.\nIn this case you can prefix all the configuration variables with\na common prefix such as: `CONF_`, `KAFKA_`, `ZK_` etc and\nhave `synapse` to replace what follows with a property with the same\nname and with the value of the variable.\n\nFor example, if you want to set a property called `log.flush.interval.ms`\nand `log.roll.hours` but you don't want to have an entry for every\nsingle Kafka broker configuration option you can add in your template\nfile the following resolver entry.\n\n```\n# Resolve any environment varible starting with KAFKA_\n%%prefix\u003eKAFKA_%%\n```\n\nIf the following configuration variable are present:\n\n``` bash\nexport KAFKA_LOG_FLUSH_INTERVAL_MS=300000\nexport KAFKA_LOG_ROLL_HOURS=200\n```\n\nit will be expanded to:\n\n```\n# Resolve any environment varible starting with KAFKA_\nlog.flush.interval.ms=300000\nlog.roll.hours=200\n```\n\nYou can control the case with the `case` option and the\nseparator with `sep` as follow:\n\n```\n# change to camel case and remove the separator\n%%prefix[case=camel,sep=]\u003eKAFKA_%%\n\n# will resolve to\nlogFlushIntervalMs=300000\nlogRollHours=200\n```\n\nHere the full option description:\n\n  - `case` : (default: `lower`), one of `lower`, `camel`, `preserve`.\n             `preserve` will maintain the same case as the environment\n             variable. So if you have and environment variable\n             `CONF_Foo_someOtherKey=200` and a resolver of\n             `%%prefix[case=preserve]\u003eCONF_%%` will resolve to\n             `Foo.someOtherKey=200`\n  - `sep`  : (default: `.` dot), the separator used to replace `_`\n  - `type` : (default: `properties`), Currently it's the only\n             supported option.\n\n#### `docker` resolver\n\nThe docker resolver uses the standard environment variable structure\ndefined in this https://docs.docker.com/v1.9/compose/env/ page.\nBasically if you are trying to link the DB with port 5432\nto your container it will look for environment variables with\nthe following names `DB_PORT_5432_TCP_ADDR`, `DB_PORT_5432_TCP_PORT`\nand `DB_PORT_5432_TCP` and use then to resolve the address and port.\n\nSo if you have to add the location of the DB in your configuration\nfiles you need just to put the following tag `%%docker\u003eDB:5432%%`\nand it will be replaced with the actual container ip address and port.\nYou can also shorten the tag by omitting the `docker` resolver name\nso the previous tag could be written as `%%\u003eDB:5432%%`.\n\nMany times you expect more than one db node to be linked to a container\nso that if a particular node is down you can still connect to another one\nand oftentimes they are named as `DB` plus a number such as: `DB1`, `DB2`,\n`DB3` etc. If you want to get a comma-separated list of them you can\njust add another angle bracket `\u003e` in the previous tag and give a pattern\nfor the tag name like: `%%\u003e\u003eDB.*:5432%%`. Note the double angle brackets `\u003e\u003e`\nwhich means you expect more than one and you wish to get a comma-separated\nlist of their values.\n\n\n## Synapse library usage\n\nSynapse can be used as a Clojure library to configure your service.\nOne way to use it is to create your configuration files as EDN files\nand place the resolvable tags in the places you wish to configure.\nFor example you could replace `username` and `password` pairs with\nenvironment variables.\n\nFirstly add the dependency to your project dependencies:\n\n[![Clojars Project](https://img.shields.io/clojars/v/com.brunobonacci/synapse.svg)](https://clojars.org/com.brunobonacci/synapse)\n\n    [com.brunobonacci/synapse \"0.4.0\"]\n\nThen prepare a configuration file such as: `config.edn`\n\n``` clojure\n{:database\n  {:host \"%%\u003edatabase:12345||localhost%%\"\n   :username \"%%DB_USER%%\"\n   :password \"%%DB_PASS%%\"}}\n```\n\nSet in your environment the vars (or add a default):\n\n``` bash\nexport DB_USER=\"your-user\"\nexport DB_PASS=\"secret\"\n```\n\nIn your program add the require:\n\n``` clojure\n(ns your.namspace\n  (:require [synapse.synapse :refer [load-config-file!]))\n\n```\n\nNow you can load the configuration file directly with:\n\n``` clojure\n(def config (load-config-file! \"./config.edn\"))\n\n;; =\u003e {:database {:host \"localhost\", :username \"your-user\", :password \"secret\"}}\n```\n\nIf any error occur an exception will be thrown. If you don't want the exception\nto be thrown you can you use `load-config-file` (without bang `!`) which returns\na vector of the configuration or `nil` and the error (as `[ config error ]`).\n\n``` clojure\n(let [[config error] (load-config-file \"./config.edn\"))]\n  config)\n;; =\u003e {:database {:host \"localhost\", :username \"your-user\", :password \"secret\"}}\n```\n\n## License\n\nCopyright © 2016-2019 Bruno Bonacci\n\nDistributed under the Apache 2 License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrunobonacci%2Fsynapse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrunobonacci%2Fsynapse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrunobonacci%2Fsynapse/lists"}