{"id":20407834,"url":"https://github.com/restorando/chef-service_discovery","last_synced_at":"2026-02-25T16:34:30.182Z","repository":{"id":9675908,"uuid":"11619099","full_name":"restorando/chef-service_discovery","owner":"restorando","description":"Give Chef superpowers to discover your services","archived":false,"fork":false,"pushed_at":"2016-11-26T20:16:09.000Z","size":15,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-06-03T14:15:20.162Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/restorando.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2013-07-23T21:01:17.000Z","updated_at":"2020-10-21T20:22:20.000Z","dependencies_parsed_at":"2022-09-01T05:02:07.685Z","dependency_job_id":null,"html_url":"https://github.com/restorando/chef-service_discovery","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/restorando/chef-service_discovery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restorando%2Fchef-service_discovery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restorando%2Fchef-service_discovery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restorando%2Fchef-service_discovery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restorando%2Fchef-service_discovery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/restorando","download_url":"https://codeload.github.com/restorando/chef-service_discovery/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restorando%2Fchef-service_discovery/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29830282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T15:41:19.027Z","status":"ssl_error","status_checked_at":"2026-02-25T15:40:47.150Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-11-15T05:26:28.243Z","updated_at":"2026-02-25T16:34:30.150Z","avatar_url":"https://github.com/restorando.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# service_discovery Cookbook\n\n`service_discovery` is a library cookbook aiming at solving the systems integration problem with Chef. It allows you to announce services and discover them from client nodes. It uses the Chef server as a discovery mechanism and supports publishing metadata like port, host, protocol, data center, cluster, etc.\n\n## Usage\n\n### Announcing services\n\nYou can announce services using the DSL method `announce_service`. It requires a service name and a hash of parameters that specify where to find it and how to connect to it.\n\nThe service name can be any string or symbol. The expected parameters are the following:\n\n- `cluster`: The name of the cluster the service belongs to. If ommitted, it will default to the value of `node['cluster']`.\n- `data_center`: The data center where the node is hosted. If omitted, it will default to the value of `node['data_center']`.\n- `environment`: The environment where the service is running. If omitted, it will default to the value of `node.chef_environment`.\n- `listening_on`: This is a required parameter. It is an array of hashes where each hash represents a connection endpoint to the service. Each endpoint can be described with the following properties:\n\t* `address`: It can be an IP address or a hostname. It defaults to `0.0.0.0`.\n  * `scope`: The network scope the services is listening on. It can be `node` (lookback interface), `private` (private network), or `public` (public internet). If the `address` is provided, the `scope` is guessed automatically. Otherwise, the `address` will be guessed with the given `scope`.\n  * `port`: A tcp or udp port number.\n  * `socket_type`: It can be tcp, udp, or unix. Defaults to tcp.\n  * `protocol`: A protocol the service understands like http, amqp, smtp, mysql, etc.\n  * `url`: A connection url like `mysql://user:pass@host:port`. The url will be parsed and used to fill the rest of the properties.\n\n#### Examples\n\nAnnouncing a Redis master instance with a connection url:\n\n```ruby\nannounce_service :redis_master, {\n  cluster: 'my-app',\n  listening_on: [\n    { url: \"redis://#{node['ipaddress']}:6379\" }\n  ]\n}\n```\n\nAnnouncing a redis slave instance with connection parameters:\n\n```ruby\nannounce_service :redis_slave, {\n  cluster: 'my-app',\n  listening_on: [{\n    scope: :private_ipv4,\n    port: 6379,\n    protocol: 'redis'\n  }]\n}\n```\n\nAnnouncing a RabbitMQ server:\n\n```ruby\nannounce_service :rabbitmq, {\n  listening_on: [{\n    protocol: 'amqp',\n    address: node['rabbitmq']['address'] || '0.0.0.0',\n    port: node['rabbitmq']['port'] || 5672\n  }, {\n    protocol: 'amqps',\n    address: node['rabbitmq']['address'] || '0.0.0.0',\n    port: node['rabbitmq']['ssl_port'] || 5671\n  }, {\n    protocol: 'https',\n    address: node['rabbitmq']['management']['host'] || '0.0.0.0',\n    port: node['rabbitmq']['management']['port'] || 15672\n  }]\n}\n```\n\nAnnouncing a MySQL server:\n\n```ruby\nannounce_service :mysql_master, {\n  listening_on: [\n    { protocol: 'mysql', address: '/var/lib/mysql/mysql.sock', socket_type: 'unix' },\n    { protocol: 'mysql', address: '127.0.0.1', port: 3306 },\n    { url: 'mysql://10.30.100.42:3306' },\n    { protocol: 'mysql', address: '200.12.132.11', port: 3306, scope: 'public' },\n    { protocol: 'memcached', address: 'private_ipv4', port: 4432 }\n  ],\n  cluster: \"my-db-cluster\",\n  data_center: 'nydc01',\n  environment: 'qa'\n}\n```\n\n### Discovering services\n\nThere are two DSL methods to discover services, `discover_nodes_for` and `discover_connection_endpoints_for`.\n\n`discover_nodes_for` gives you a list of nodes where the service you're looking for is running. It accepts two parameters, a service id and a hash of properties to scope the search. These properties are:\n\n- `environment_aware`: It's a boolean parameter that scopes the search to a given environment. By default, `node.chef_environment`. Defaults to `true`.\n- `environment`: The environment to scope the search.\n- `cluster_aware`: It's a boolean parameter that scopes the search to a given cluster. By default, `node['cluster']`. Defaults to `true`.\n- `cluster`: The cluster to scope the search.\n- `data_center_aware`: It's a boolean parameter that scopes the search to a given data center. By default, `node['data_center']`. Defaults to `false`.\n- `data_center`: The data center to scope the search.\n- `exclude_self`: It's a boolean parameter to exlcude the current node from results in case it appears in the search.\n\n`discover_connection_endpoints_for` gives you a list of endpoints to connect to. It accepts the same parameters as `discover_nodes_for`, and a few additions:\n\n- `node`: Scopes the search to the given node.\n- `nodes`: Scopes the search to a list of nodes.\n- `require`: It's a hash of required attributes for the endpoints, like `protocol`, `port`, `scope`, etc.\n\nIt will also find the closet endpoints to the node performing the search. For instance, let's say you have a service `foo` running in nodes `A`, `B`, `C` and listing on all the available interfaces. Nodes `A` and `B` are in the same network, node `C` is not.\nIf you perform the search from node `A` you will get endpoints for loopback in `A`, private ip address in `B` and public ip in `C`.\n\n#### Examples\n\nDiscover nodes for a mysql service in a certain environment and cluster:\n\n```ruby\nnodes = discover_nodes_for :mysql_server, exclude_self: true, environment: 'qa', cluster: 'my-db-cluster'\n```\n\nGet a list of host and port pairs for a mysql service with memcached endpoints:\n\n```ruby\nhost_port_pair = discover_connection_endpoints_for(:mysql_server, {\n                   cluster: 'my-db-cluster',\n                   data_center_aware: true,\n                   data_center: 'nydc01',\n                   require: { protocol: 'memcached', socket_type: 'tcp' }\n                 }).map do |endpoint|\n  [endpoint[:address], endpoint[:port] || 3306].join(\":\")\nend\n```\n\nGet a list of endpoints to connect to a rabbitmq broker:\n\n```ruby\ndiscover_connection_endpoints_for :rabbitmq, {\n  cluster: 'amqp01',\n  require: { protocol: 'amqp' }\n}\n```\n\nGet a list of endpoints for the rabbitmq management interface:\n\n```ruby\ndiscover_connection_endpoints_for :rabbitmq, {\n  cluster: 'amqp01',\n  require: { protocol: 'https', port: 15672 }\n}\n```\n\n## Similar projects\n\nThis cookbook was inspired by:\n\n- [Silverware](https://github.com/infochimps-labs/ironfan-pantry/tree/master/cookbooks/silverware)\n- [Discovery](https://github.com/hw-cookbooks/discovery)\n\n\n## License\n\nCopyright (c) 2013 Restorando\n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frestorando%2Fchef-service_discovery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frestorando%2Fchef-service_discovery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frestorando%2Fchef-service_discovery/lists"}