resource_name :consul_service provides :consul_service unified_mode true property :service_name, String, name_property: true property :id, String, name_property: true property :ip_address, [String, nil], default: nil property :meta, [Hash, nil], default: nil property :port, [Integer, nil], default: nil property :reload_service, [TrueClass, FalseClass], default: true # Combined address plus port - 0.0.0.0:1234 property :socket_address, [String, nil], default: nil action :create do if property_is_set?(:socket_address) ip_address, port = new_resource.socket_address.split(':') ip_address = translate_address(ip_address) elsif property_is_set?(:ip_address) && property_is_set?(:port) ip_address = translate_address(new_resource.ip_address) port = new_resource.port else raise "Missing required properties: `socket_address` or both `ip_address` and `port`." end service_name = sanitize_service_name(new_resource.service_name) file_name = sanitize_service_name(new_resource.id) content = { 'service' => { 'name' => service_name, 'address' => ip_address, 'port' => port.to_i } } # Remove address if advertise_addr is set to allow service to use underlying advertise_addr content['service'].delete('address') if node['consul']['configuration']['advertise_addr'] content['service']['meta'] = new_resource.meta if property_is_set?(:meta) # Ensure the dir exists but leave permissions to `consul::enable` directory node['consul']['config_dir'] do recursive true end file "#{node['consul']['config_dir']}/#{file_name}-service.json" do content content.to_json notifies :run, 'execute[reload consul]' if new_resource.reload_service end end action :delete do file_name = sanitize_service_name(new_resource.id) file "#{node['consul']['config_dir']}/#{file_name}-service.json" do action :delete notifies :run, 'execute[reload consul]' if new_resource.reload_service end end # Consul allows dashes but not underscores for DNS service discovery. # Avoid logging errors by changing all underscores to dashes. def sanitize_service_name(name) name.tr('_', '-') end # A listen address of 0.0.0.0 binds to all interfaces. # Translate that listen address to the node's actual # IP address so external services know where to connect. def translate_address(address) return node['ipaddress'] if ['0.0.0.0', '*'].include?(address) address end