Skip to content

Commit

Permalink
change: check etcd cluster version when init_etcd
Browse files Browse the repository at this point in the history
Signed-off-by: tokers <zchao1995@gmail.com>
  • Loading branch information
tokers committed Sep 16, 2020
1 parent 4722198 commit da05a15
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 31 deletions.
135 changes: 105 additions & 30 deletions bin/apisix
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ local function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end

-- Note: The `excute_cmd` return value will have a line break at the end,
-- Note: The `execute_cmd` return value will have a line break at the end,
-- it is recommended to use the `trim` function to handle the return value.
local function excute_cmd(cmd)
local function execute_cmd(cmd)
local t, err = io.popen(cmd)
if not t then
return nil, "failed to execute command: " .. cmd .. ", error info:" .. err
Expand All @@ -33,7 +33,7 @@ local function excute_cmd(cmd)
return data
end

excute_cmd("install -d -m 777 /tmp/apisix_cores/")
execute_cmd("install -d -m 777 /tmp/apisix_cores/")

local pkg_cpath_org = package.cpath
local pkg_path_org = package.path
Expand All @@ -42,12 +42,14 @@ local apisix_home = "/usr/local/apisix"
local pkg_cpath = apisix_home .. "/deps/lib64/lua/5.1/?.so;"
.. apisix_home .. "/deps/lib/lua/5.1/?.so;;"
local pkg_path = apisix_home .. "/deps/share/lua/5.1/?.lua;;"
local min_etcd_version = "3.4.0"


-- only for developer, use current folder as working space
local is_root_path = false
local script_path = arg[0]
if script_path:sub(1, 2) == './' then
apisix_home = trim(excute_cmd("pwd"))
apisix_home = trim(execute_cmd("pwd"))
if not apisix_home then
error("failed to fetch current path")
end
Expand Down Expand Up @@ -605,14 +607,6 @@ local function merge_conf(base, new_tab)
return base
end

local function str_split(str, sep)
local t = {}
for s in str:gmatch("([^"..sep.."]+)") do
table.insert(t, s)
end
return t
end


local function read_yaml_conf()
local profile = require("apisix.core.profile")
Expand Down Expand Up @@ -654,16 +648,17 @@ local function read_yaml_conf()
return default_conf
end


local function get_openresty_version()
local str = "nginx version: openresty/"
local ret = excute_cmd("openresty -v 2>&1")
local ret = execute_cmd("openresty -v 2>&1")
local pos = string.find(ret,str)
if pos then
return string.sub(ret, pos + string.len(str))
end

str = "nginx version: nginx/"
ret = excute_cmd("openresty -v 2>&1")
ret = execute_cmd("openresty -v 2>&1")
pos = string.find(ret, str)
if pos then
return string.sub(ret, pos + string.len(str))
Expand All @@ -672,23 +667,82 @@ local function get_openresty_version()
return nil
end


local function is_32bit_arch()
local ok, ffi = pcall(require, "ffi")
if ok then
-- LuaJIT
return ffi.abi("32bit")
end
local ret = excute_cmd("getconf LONG_BIT")
local ret = execute_cmd("getconf LONG_BIT")
local bits = tonumber(ret)
return bits <= 32
end


local function split(self, sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
self:gsub(pattern, function(c) fields[#fields + 1] = c end)
return fields
end
end


local function parse_semantic_version(ver)
local errmsg = "invalid semantic version: " .. ver

local parts = split(ver, "-")
if #parts > 2 then
return nil, errmsg
end

if #parts == 2 then
ver = parts[1]
end

local fields = split(ver, ".")
if #fields ~= 3 then
return nil, errmsg
end

local major = tonumber(fields[1])
local minor = tonumber(fields[2])
local patch = tonumber(fields[3])

if not (major and minor and patch) then
return nil, errmsg
end

return {
major = major,
minor = minor,
patch = patch,
}
end


local function compare_semantic_version(v1, v2)
local ver1, err = parse_semantic_version(v1)
if not ver1 then
return nil, err
end

local ver2, err = parse_semantic_version(v2)
if not ver2 then
return nil, err
end

if ver1.major ~= ver2.major then
return ver1.major < ver2.major
end

if ver1.minor ~= ver2.minor then
return ver1.minor < ver2.minor
end

return ver1.patch < ver2.patch
end


local function check_version(cur_ver_s, need_ver_s)
local cur_vers = split(cur_ver_s, [[.]])
Expand Down Expand Up @@ -758,7 +812,7 @@ local function init()
end
-- print("etcd: ", yaml_conf.etcd.host)

local or_ver = excute_cmd("openresty -V 2>&1")
local or_ver = execute_cmd("openresty -V 2>&1")
local with_module_status = true
if or_ver and not or_ver:find("http_stub_status_module", 1, true) then
io.stderr:write("'http_stub_status_module' module is missing in ",
Expand All @@ -780,7 +834,7 @@ local function init()
local sys_conf = {
lua_path = pkg_path_org,
lua_cpath = pkg_cpath_org,
os_name = trim(excute_cmd("uname")),
os_name = trim(execute_cmd("uname")),
apisix_lua_home = apisix_home,
with_module_status = with_module_status,
error_log = {level = "warn"},
Expand Down Expand Up @@ -885,20 +939,40 @@ local function init_etcd(show_output)
yaml_conf.etcd.host = {yaml_conf.etcd.host}
end

local cluster_version
local host_count = #(yaml_conf.etcd.host)
local dkjson = require("dkjson")

local etcd_ok = false
-- check the etcd cluster version
for index, host in ipairs(yaml_conf.etcd.host) do
-- check if etcd version above 3.4
cmd = "curl " .. host .. "/version 2>&1"
local res = excute_cmd(cmd)
local op_ver = str_split(res, "\"")[4]
local need_ver = "3.4.0"
if not check_version(op_ver, need_ver) then
io.stderr:write("etcd version must >=", need_ver, " current ", op_ver, "\n")
uri = host .. "/version"
local cmd = string.format("curl -s -m %d %s", timeout * 2, uri)
local res = execute_cmd(cmd)
local errmsg = string.format("got malformed version message: \"%s\" from etcd", res)
local body, _, err = dkjson.decode(res)
if err then
io.stderr:write(errmsg)
return
end

local cluster_version = body["etcdcluster"]
if not cluster_version then
io.stderr:write(errmsg)
return
end

if compare_semantic_version(cluster_version, min_etcd_version) then
io.stderr:write("etcd cluster version ", cluster_version,
" is less than the required version ", min_etcd_version,
", please upgrade your etcd cluster")
return
end

break
end

local etcd_ok = false
for index, host in ipairs(yaml_conf.etcd.host) do
local is_success = true

for _, dir_name in ipairs({"/routes", "/upstreams", "/services",
Expand All @@ -910,16 +984,17 @@ local function init_etcd(show_output)
local base64_encode = require("base64").encode
local uri = host .. "/v3/kv/put"
local post_json = '{"value":"' .. base64_encode("init_dir") .. '", "key":"' .. base64_encode(key) .. '"}'
cmd = "curl " .. uri .. " -X POST -d '" .. post_json
.. "' --connect-timeout " .. timeout
.. " --max-time " .. timeout * 2 .. " --retry 1 2>&1"
local cmd = "curl " .. uri .. " -X POST -d '" .. post_json
.. "' --connect-timeout " .. timeout
.. " --max-time " .. timeout * 2 .. " --retry 1 2>&1"

local res = excute_cmd(cmd)
local res = execute_cmd(cmd)
if (etcd_version == "v3" and not res:find("OK", 1, true)) then
is_success = false
if (index == host_count) then
error(cmd .. "\n" .. res)
end

break
end

Expand Down
3 changes: 2 additions & 1 deletion rockspec/apisix-master-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ dependencies = {
"lua-resty-kafka = 0.07",
"lua-resty-logger-socket = 2.0-0",
"skywalking-nginx-lua-plugin = 1.0-0",
"base64 = 1.5-2"
"base64 = 1.5-2",
"dkjson = 2.5-2",
}

build = {
Expand Down

0 comments on commit da05a15

Please sign in to comment.