Skip to content

Commit

Permalink
Removing dnsmasq dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
subnetmarco committed May 17, 2016
1 parent b6d0df6 commit 6f7b6d9
Show file tree
Hide file tree
Showing 15 changed files with 222 additions and 118 deletions.
2 changes: 1 addition & 1 deletion kong-0.8.1-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ build = {
["kong.cli.utils.ssl"] = "kong/cli/utils/ssl.lua",
["kong.cli.utils.input"] = "kong/cli/utils/input.lua",
["kong.cli.utils.services"] = "kong/cli/utils/services.lua",
["kong.cli.utils.dns"] = "kong/cli/utils/dns.lua",
["kong.cli.cmds.config"] = "kong/cli/cmds/config.lua",
["kong.cli.cmds.quit"] = "kong/cli/cmds/quit.lua",
["kong.cli.cmds.stop"] = "kong/cli/cmds/stop.lua",
Expand All @@ -65,7 +66,6 @@ build = {
["kong.cli.cmds.migrations"] = "kong/cli/cmds/migrations.lua",
["kong.cli.cmds.cluster"] = "kong/cli/cmds/cluster.lua",
["kong.cli.services.base_service"] = "kong/cli/services/base_service.lua",
["kong.cli.services.dnsmasq"] = "kong/cli/services/dnsmasq.lua",
["kong.cli.services.serf"] = "kong/cli/services/serf.lua",
["kong.cli.services.nginx"] = "kong/cli/services/nginx.lua",

Expand Down
23 changes: 10 additions & 13 deletions kong.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,17 @@
# ssl_key_path: /path/to/certificate.key

######
## Specify how Kong performs DNS resolution (in the `dns_resolvers_available` property) you want to use.
## Options are: "dnsmasq" (You will need dnsmasq to be installed) or "server".
# dns_resolver: dnsmasq
## By default Kong will resolve DNS addresses using the local system settings as configured in `/etc/resolv.conf`
## and `/etc/hosts`. You can customize the DNS resolution settings by changing the following properties.
#dns_resolver:

######
## A dictionary of DNS resolvers Kong can use, and their respective properties.
## Currently `dnsmasq` (default, http://www.thekelleys.org.uk/dnsmasq/doc.html) and `server` are supported.
## By choosing `dnsmasq`, Kong will resolve hostnames using the local `/etc/hosts` file and `resolv.conf`
## configuration. By choosing `server`, you can specify a custom DNS server.
# dns_resolvers_available:
# server:
# address: "8.8.8.8:53"
# dnsmasq:
# port: 8053
######
## You can override the DNS server being used by specifying a custom DNS server.
# address: "8.8.8.8:53"

######
## SRV record resolutions are enabled by default. Disabling them will slightly improve the performance.
# srv: true

######
## Cluster settings between Kong nodes.
Expand Down
52 changes: 0 additions & 52 deletions kong/cli/services/dnsmasq.lua

This file was deleted.

2 changes: 2 additions & 0 deletions kong/cli/services/nginx.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ local function prepare_nginx_configuration(configuration, ssl_config)

local current_user = get_current_user()

logger:info("DNS resolver set to "..configuration.dns_resolver.address.." on port "..configuration.dns_resolver.port)

-- Extract nginx config from kong config, replace any needed value
local nginx_config = configuration.nginx
local nginx_inject = {
Expand Down
80 changes: 80 additions & 0 deletions kong/cli/utils/dns.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
local stringy = require "stringy"
local IO = require "kong.tools.io"
local utils = require "kong.tools.utils"

local _M = {}

function _M.parse_dns_address(address)
local with_port = string.match(address, "%[")
local parts = stringy.split(address, ":")
return {
address = address,
host = address:match("%[?([%w%.:]+)%]?"),
port = with_port and tonumber(parts[#parts]) or 53
}
end

function _M.parse_resolv_entry(v)
local address = v:match("%s*nameserver%s+([%[%]%w%.:]+)")
if address then
return _M.parse_dns_address(address)
end
end

function _M.parse_options_entry(v)
local options = v:match("%s*options%s+[%s%w:]+")
if options then
local timeout, attempts
for option in options:gmatch("%S+") do
timeout = timeout or tonumber(option:match("%s*timeout:(%d+)%s*"))
attempts = attempts or tonumber(option:match("%s*attempts:(%d+)%s*"))
end

if timeout or attempts then
return {timeout = timeout and timeout * 1000 or timeout, attempts = attempts} -- In milliseconds
end
end
end

function _M.parse_etc_hosts()
local contents = IO.read_file("/etc/hosts")
if contents then
local results = {}
local lines = stringy.split(contents, "\n")
for _, line in ipairs(lines) do
if not stringy.startswith(stringy.strip(line), "#") then
local ip_address
for entry in line:gmatch("%S+") do
if not ip_address then
ip_address = entry
else
if not results[entry] then
results[entry] = ip_address
end
end
end
end
end
return results
end
end

function _M.find_first_namespace()
local contents = IO.read_file("/etc/resolv.conf")
if contents then
-- Find first nameserver
local lines = stringy.split(contents, "\n")
local options, nameserver

for _, line in ipairs(lines) do
nameserver = nameserver or _M.parse_resolv_entry(line)
options = options or _M.parse_options_entry(line)
end

if nameserver then
return utils.table_merge(nameserver, options and options or {})
end
end
end

return _M
1 change: 0 additions & 1 deletion kong/cli/utils/services.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ _M.STATUSES = {

-- Services ordered by priority
local services = {
require "kong.cli.services.dnsmasq",
require "kong.cli.services.serf",
require "kong.cli.services.nginx"
}
Expand Down
21 changes: 15 additions & 6 deletions kong/core/resolver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,21 @@ function _M.execute(request_uri, request_headers)
upstream_host = parsed_url.host..":"..upstream_port
end

-- Resolve the appropriate DNS
local dns = DnsResolver(singletons.configuration.dns_resolver.address)
local resolution, err = dns:resolve(parsed_url.host, parsed_url.port)
if err then
ngx.log(ngx.ERR, err)
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
-- Resolve the appropriate DNS address, first by checking /etc/hosts, then by invoking the DNS server
local resolution
local etc_host = singletons.configuration.dns_etc_hosts[parsed_url.host] -- Check /etc/hosts first
if etc_host then
resolution = {host = etc_host}
else
-- Resolve using the DNS server
local dns_config = singletons.configuration.dns_resolver
local dns = DnsResolver(dns_config.host, dns_config.port, dns_config.timeout, dns_config.attempts)
local err
resolution, err = dns:resolve(parsed_url.host, parsed_url.port, dns_config.srv)
if err then
ngx.log(ngx.ERR, err)
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err) --TODO: this throw an error even when the resolution fails, it should return 502 (?)
end
end

if not resolution.port then
Expand Down
17 changes: 3 additions & 14 deletions kong/tools/config_defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,11 @@ return {
["admin_api_listen"] = {type = "string", default = "0.0.0.0:8001"},
["cluster_listen"] = {type = "string", default = "0.0.0.0:7946"},
["cluster_listen_rpc"] = {type = "string", default = "127.0.0.1:7373"},
["dns_resolver"] = {type = "string", default = "dnsmasq", enum = {"server", "dnsmasq"}},
["dns_resolvers_available"] = {
["dns_resolver"] = {
type = "table",
content = {
["server"] = {
type = "table",
content = {
["address"] = {type = "string", default = "8.8.8.8"}
}
},
["dnsmasq"] = {
type = "table",
content = {
["port"] = {type = "number", default = 8053}
}
}
["address"] = {type = "string", nullable = false},
["srv"] = {type = "boolean", default = true}
}
},
["cluster"] = {
Expand Down
20 changes: 13 additions & 7 deletions kong/tools/config_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local logger = require "kong.cli.utils.logger"
local stringy = require "stringy"
local constants = require "kong.constants"
local config_defaults = require "kong.tools.config_defaults"
local dns_utils = require "kong.cli.utils.dns"

local function get_type(value, val_type)
if val_type == "array" and utils.is_array(value) then
Expand Down Expand Up @@ -178,14 +179,19 @@ function _M.load(config_path)
-- Adding computed properties
config.pid_file = IO.path:join(config.nginx_working_dir, constants.CLI.NGINX_PID)
config.dao_config = config[config.database]
if config.dns_resolver == "dnsmasq" then
config.dns_resolver = {
address = "127.0.0.1:"..config.dns_resolvers_available.dnsmasq.port,
port = config.dns_resolvers_available.dnsmasq.port,
dnsmasq = true
}

-- DNS resolver
config.dns_etc_hosts = dns_utils.parse_etc_hosts()
if config.dns_resolver and config.dns_resolver.address then
config.dns_resolver = dns_utils.parse_dns_address(config.dns_resolver.address)
else
config.dns_resolver = {address = config.dns_resolvers_available.server.address}
-- Find from resolv.conf
local resolv_nameserver = dns_utils.find_first_namespace()
if not resolv_nameserver then
logger:error("Can't parse the system DNS settings. Please manually specify a DNS resolver in the configuaration")
os.exit(1)
end
config.dns_resolver = resolv_nameserver
end

-- Load absolute path for the nginx working directory
Expand Down
34 changes: 19 additions & 15 deletions kong/tools/dns_resolver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ local stringy = require "stringy"
local cache = require "kong.tools.database_cache"
local resolver = require "resty.dns.resolver"

local DEFAULT_TIMEOUT = 2000
local DEFAULT_ATTEMPTS = 5

local DnsResolver = Object:extend()

function DnsResolver:new(resolver_address)
local dns_resolver_parts = stringy.split(resolver_address, ":")
self.resolver = {
host = dns_resolver_parts[1],
port = dns_resolver_parts[2]
}
function DnsResolver:new(host, port, timeout, attempts)
self.host = host
self.port = port
self.timeout = timeout or DEFAULT_TIMEOUT
self.attempts = attempts or DEFAULT_ATTEMPTS
end

function DnsResolver:query(address, type)
-- Init the resolver
local r, err = resolver:new{
nameservers = {{self.resolver.host, self.resolver.port}},
retrans = 5,
timeout = 2000
nameservers = {{self.host, self.port}},
retrans = self.attempts,
timeout = self.timeout
}
if not r then
return nil, "Startup error: "..err
Expand All @@ -37,7 +39,7 @@ function DnsResolver:query(address, type)
return answers
end

function DnsResolver:resolve(address, port)
function DnsResolver:resolve(address, port, enable_srv)
-- Retrieve from cache
local cache_key = cache.dns_key(address)
local result = cache.get(cache_key)
Expand All @@ -59,11 +61,13 @@ function DnsResolver:resolve(address, port)

-- Query for SRV record
local final_port = port
local answers, err = self:query(address, "SRV")
if not err and #answers > 0 then -- Ignore the error because some DNS servers don't support SRV
local srv_answer = answers[1]
if srv_answer.port > 0 then
final_port = srv_answer.port
if enable_srv then
local answers, err = self:query(address, "SRV")
if not err and #answers > 0 then -- Ignore the error because some DNS servers don't support SRV
local srv_answer = answers[1]
if srv_answer.port > 0 then
final_port = srv_answer.port
end
end
end

Expand Down
4 changes: 2 additions & 2 deletions spec/integration/04-admin_api/apis_routes_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe("Admin API", function()
assert.equal(201, status)
end
end)
it_content_types("#only should not update if some required fields are missing", function(content_type)
it_content_types("should not update if some required fields are missing", function(content_type)
return function()
local response, status = http_client.put(BASE_URL, {
id = api.id,
Expand All @@ -104,7 +104,7 @@ describe("Admin API", function()
assert.equal("created_at is required", body.created_at)
end
end)
it_content_types("#only should update if exists", function(content_type)
it_content_types("should update if exists", function(content_type)
return function()
local response, status = http_client.put(BASE_URL, {
id = api.id,
Expand Down
2 changes: 1 addition & 1 deletion spec/plugins/oauth2/api_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ describe("OAuth 2 Credentials API", function()
end)

describe("PUT", function()
it("#only [SUCCESS] should create a oauth2 token", function()
it("[SUCCESS] should create a oauth2 token", function()
local response, status = http_client.put(BASE_URL, {credential_id = credential.id, expires_in = 10})
assert.equal(201, status)
token = json.decode(response)
Expand Down
5 changes: 0 additions & 5 deletions spec/unit/14-config_loader_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ describe("Configuration validation", function()
end
end)
end)
it("should validate the selected dns_resolver property", function()
local ok, errors = config.validate({dns_resolver = "foo"})
assert.False(ok)
assert.equal("must be one of: 'server, dnsmasq'", errors.dns_resolver)
end)
it("should validate the host:port listen addresses", function()
-- Missing port
local ok, errors = config.validate({proxy_listen = "foo"})
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/16-resolver_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ singletons.dao = {
}

singletons.configuration = {
dns_resolver = {address="127.0.0.1:8053"}
dns_resolver = {address="8.8.8.8:53"}
}

local apis_dics
Expand Down
Loading

0 comments on commit 6f7b6d9

Please sign in to comment.