You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2021/02/02 01:07:52 UTC

[apisix] branch master updated: feat: switch resolver to lua-resty-dns-client (#3442)

This is an automated email from the ASF dual-hosted git repository.

spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 563b259  feat: switch resolver to lua-resty-dns-client (#3442)
563b259 is described below

commit 563b259a5a632b4776e253dd6fefc9d20b88a8f9
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Tue Feb 2 09:07:40 2021 +0800

    feat: switch resolver to lua-resty-dns-client (#3442)
    
    Signed-off-by: spacewander <sp...@gmail.com>
---
 .travis/linux_openresty_common_runner.sh |  4 +-
 apisix/core/utils.lua                    | 92 ++++++++++++++++++--------------
 rockspec/apisix-master-0.rockspec        |  1 +
 t/core/utils.t                           | 48 ++++++++++++++++-
 t/grpc-proxy-test.sh                     |  2 -
 t/node/upstream-node-dns.t               | 16 +++---
 t/plugin/limit-count.t                   |  4 +-
 utils/centos7-ci.sh                      |  1 +
 utils/set-dns.sh                         | 26 +++++++++
 9 files changed, 139 insertions(+), 55 deletions(-)

diff --git a/.travis/linux_openresty_common_runner.sh b/.travis/linux_openresty_common_runner.sh
index a67c1a9..fe50864 100755
--- a/.travis/linux_openresty_common_runner.sh
+++ b/.travis/linux_openresty_common_runner.sh
@@ -99,6 +99,8 @@ script() {
     export_or_prefix
     openresty -V
 
+    ./utils/set-dns.sh
+
     ./build-cache/grpc_server_example \
         -grpc-address :50051 -grpcs-address :50052 \
         -crt ./t/certs/apisix.crt -key ./t/certs/apisix.key \
@@ -129,7 +131,7 @@ script() {
     sleep 1
     cat logs/error.log
 
-    sudo sh ./t/grpc-proxy-test.sh
+    sh ./t/grpc-proxy-test.sh
     sleep 1
 
     ./bin/apisix stop
diff --git a/apisix/core/utils.lua b/apisix/core/utils.lua
index 8629d97..60e3068 100644
--- a/apisix/core/utils.lua
+++ b/apisix/core/utils.lua
@@ -14,31 +14,33 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
-local core_str = require("apisix.core.string")
-local table    = require("apisix.core.table")
-local log      = require("apisix.core.log")
-local string   = require("apisix.core.string")
-local ngx_re   = require("ngx.re")
-local resolver = require("resty.dns.resolver")
-local ipmatcher= require("resty.ipmatcher")
-local ffi      = require("ffi")
-local base     = require("resty.core.base")
-local open     = io.open
-local math     = math
-local sub_str  = string.sub
-local str_byte = string.byte
-local tonumber = tonumber
-local tostring = tostring
-local re_gsub  = ngx.re.gsub
-local type     = type
-local io_popen = io.popen
-local C        = ffi.C
-local ffi_string = ffi.string
+local core_str       = require("apisix.core.string")
+local table          = require("apisix.core.table")
+local log            = require("apisix.core.log")
+local string         = require("apisix.core.string")
+local ngx_re         = require("ngx.re")
+local dns_client     = require("resty.dns.client")
+local ipmatcher      = require("resty.ipmatcher")
+local ffi            = require("ffi")
+local base           = require("resty.core.base")
+local open           = io.open
+local math           = math
+local sub_str        = string.sub
+local str_byte       = string.byte
+local tonumber       = tonumber
+local tostring       = tostring
+local re_gsub        = ngx.re.gsub
+local type           = type
+local io_popen       = io.popen
+local C              = ffi.C
+local ffi_string     = ffi.string
 local get_string_buf = base.get_string_buf
-local exiting = ngx.worker.exiting
-local ngx_sleep    = ngx.sleep
+local exiting        = ngx.worker.exiting
+local ngx_sleep      = ngx.sleep
 
 local hostname
+local dns_resolvers
+local current_inited_resolvers
 local max_sleep_interval = 1
 
 ffi.cdef[[
@@ -80,19 +82,26 @@ function _M.split_uri(uri)
 end
 
 
-local function dns_parse(domain, resolvers)
-    resolvers = resolvers or _M.resolvers
-    local r, err = resolver:new{
-        nameservers = table.clone(resolvers),
-        retrans = 5,  -- 5 retransmissions on receive timeout
-        timeout = 2000,  -- 2 sec
-    }
+local function dns_parse(domain)
+    if dns_resolvers ~= current_inited_resolvers then
+        local opts = {
+            ipv6 = true,
+            nameservers = table.clone(dns_resolvers),
+            retrans = 5,  -- 5 retransmissions on receive timeout
+            timeout = 2000,  -- 2 sec
+        }
+        local ok, err = dns_client.init(opts)
+        if not ok then
+            return nil, "failed to init the dns client: " .. err
+        end
 
-    if not r then
-        return nil, "failed to instantiate the resolver: " .. err
+        current_inited_resolvers = dns_resolvers
     end
 
-    local answers, err = r:query(domain, nil, {})
+    log.info("dns resolve ", domain)
+
+    -- this function will dereference the CNAME records
+    local answers, err = dns_client.resolve(domain)
     if not answers then
         return nil, "failed to query the DNS server: " .. err
     end
@@ -104,21 +113,24 @@ local function dns_parse(domain, resolvers)
 
     local idx = math.random(1, #answers)
     local answer = answers[idx]
-    if answer.type == 1 then
-        return answer
-    end
-
-    if answer.type ~= 5 then
-        return nil, "unsupport DNS answer"
+    local dns_type = answer.type
+    -- TODO: support AAAA & SRV
+    if dns_type == dns_client.TYPE_A then
+        return table.deepcopy(answer)
     end
 
-    return dns_parse(answer.cname, resolvers)
+    return nil, "unsupport DNS answer"
 end
 _M.dns_parse = dns_parse
 
 
 function _M.set_resolver(resolvers)
-    _M.resolvers = resolvers
+    dns_resolvers = resolvers
+end
+
+
+function _M.get_resolver(resolvers)
+    return dns_resolvers
 end
 
 
diff --git a/rockspec/apisix-master-0.rockspec b/rockspec/apisix-master-0.rockspec
index ee08a4c..98c1416 100644
--- a/rockspec/apisix-master-0.rockspec
+++ b/rockspec/apisix-master-0.rockspec
@@ -32,6 +32,7 @@ description = {
 
 dependencies = {
     "lua-resty-ctxdump = 0.1-0",
+    "lua-resty-dns-client = 5.2.0",
     "lua-resty-template = 1.9",
     "lua-resty-etcd = 1.4.3",
     "lua-resty-balancer = 0.02rc5",
diff --git a/t/core/utils.t b/t/core/utils.t
index 3b2acec..42cba26 100644
--- a/t/core/utils.t
+++ b/t/core/utils.t
@@ -78,7 +78,7 @@ GET /t
             local core = require("apisix.core")
             local resolvers = {"8.8.8.8"}
             core.utils.set_resolver(resolvers)
-            local ip_info, err = core.utils.dns_parse("github.com", resolvers)
+            local ip_info, err = core.utils.dns_parse("github.com")
             if not ip_info then
                 core.log.error("failed to parse domain: ", host, ", error: ",err)
             end
@@ -104,7 +104,7 @@ qr/"address":.+,"name":"github.com"/
                 core.log.error("failed to parse domain: ", host, ", error: ",err)
             end
             core.log.info("ip_info: ", require("toolkit.json").encode(ip_info))
-            ngx.say("resolvers: ", require("toolkit.json").encode(core.utils.resolvers))
+            ngx.say("resolvers: ", require("toolkit.json").encode(core.utils.get_resolver()))
         }
     }
 --- request
@@ -245,3 +245,47 @@ res:John and \$me
 res:John_David
 res:JohnDavid
 res:JohnDavid
+
+
+
+=== TEST 7: resolve host from /etc/hosts
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+            local ip_info, err = core.utils.dns_parse("test.com")
+            if not ip_info then
+                core.log.error("failed to parse domain: ", host, ", error: ",err)
+                return
+            end
+            ngx.say("ip_info: ", require("toolkit.json").encode(ip_info))
+        }
+    }
+--- request
+GET /t
+--- response_body
+ip_info: {"address":"127.0.0.1","class":1,"name":"test.com","ttl":315360000,"type":1}
+--- no_error_log
+[error]
+
+
+
+=== TEST 8: search host with '.org' suffix
+--- config
+    location /t {
+        content_by_lua_block {
+            local core = require("apisix.core")
+            local ip_info, err = core.utils.dns_parse("apisix")
+            if not ip_info then
+                core.log.error("failed to parse domain: ", host, ", error: ",err)
+                return
+            end
+            ngx.say("ip_info: ", require("toolkit.json").encode(ip_info))
+        }
+    }
+--- request
+GET /t
+--- response_body_like
+.+"name":"apisix\.apache\.org".+
+--- no_error_log
+[error]
diff --git a/t/grpc-proxy-test.sh b/t/grpc-proxy-test.sh
index 6e80d17..7ffa965 100755
--- a/t/grpc-proxy-test.sh
+++ b/t/grpc-proxy-test.sh
@@ -18,8 +18,6 @@
 
 set -ex
 
-echo "127.0.0.1 test.com" | sudo tee -a /etc/hosts
-
 #set ssl
 curl http://127.0.0.1:9080/apisix/admin/ssl/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
diff --git a/t/node/upstream-node-dns.t b/t/node/upstream-node-dns.t
index f660c6e..c70e60f 100644
--- a/t/node/upstream-node-dns.t
+++ b/t/node/upstream-node-dns.t
@@ -79,7 +79,7 @@ passed
     apisix.http_init()
 
     local utils = require("apisix.core.utils")
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         if domain == "test.com" then
             return {address = "127.0.0.2"}
         end
@@ -104,7 +104,7 @@ hello world
 
     local utils = require("apisix.core.utils")
     local count = 0
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         count = count + 1
 
         if domain == "test.com" then
@@ -192,7 +192,7 @@ passed
     apisix.http_init()
 
     local utils = require("apisix.core.utils")
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         if domain == "test.com" or domain == "test2.com" then
             return {address = "127.0.0.2"}
         end
@@ -217,7 +217,7 @@ hello world
 
     local utils = require("apisix.core.utils")
     local count = 0
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         count = count + 1
 
         if domain == "test.com" or domain == "test2.com" then
@@ -345,7 +345,7 @@ passed
 
     local utils = require("apisix.core.utils")
     local count = 0
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         count = count + 1
 
         if domain == "test.com" then
@@ -432,7 +432,7 @@ passed
 
     local utils = require("apisix.core.utils")
     local count = 0
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         count = count + 1
 
         if domain == "test.com" or domain == "test2.com" then
@@ -501,7 +501,7 @@ proxy request to 127.0.0.[56]:1980
 
     local utils = require("apisix.core.utils")
     local count = 1
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         if domain == "test.com" or domain == "test2.com" then
             return {address = "127.0.0.1"}
         end
@@ -600,7 +600,7 @@ passed
 
     local utils = require("apisix.core.utils")
     local count = 0
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         count = count + 1
         if domain == "test.com" or domain == "test2.com" then
             return {address = "127.0.0." .. count}
diff --git a/t/plugin/limit-count.t b/t/plugin/limit-count.t
index 7cf8f4f..3a5f8a5 100644
--- a/t/plugin/limit-count.t
+++ b/t/plugin/limit-count.t
@@ -1240,7 +1240,7 @@ passed
     apisix.http_init()
 
     local utils = require("apisix.core.utils")
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         if domain == "test.com" then
             return {address = "127.0.0.1"}
         end
@@ -1310,7 +1310,7 @@ passed
     apisix.http_init()
 
     local utils = require("apisix.core.utils")
-    utils.dns_parse = function (domain, resolvers)  -- mock: DNS parser
+    utils.dns_parse = function (domain)  -- mock: DNS parser
         if domain == "test.com" then
             return {address = "127.0.0.1"}
         end
diff --git a/utils/centos7-ci.sh b/utils/centos7-ci.sh
index 9e8d817..b65a5e5 100755
--- a/utils/centos7-ci.sh
+++ b/utils/centos7-ci.sh
@@ -72,6 +72,7 @@ run_case() {
 
     cd apisix
 
+    ./utils/set-dns.sh
     # run test cases
     prove -Itest-nginx/lib -I./ -r t/
 }
diff --git a/utils/set-dns.sh b/utils/set-dns.sh
new file mode 100755
index 0000000..618b033
--- /dev/null
+++ b/utils/set-dns.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -ex
+
+echo "127.0.0.1 test.com" | sudo tee -a /etc/hosts
+cat /etc/hosts # check GitHub Action's configuration
+
+echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
+echo "search apache.org" | sudo tee -a /etc/resolv.conf