diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..d6e7814860 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @wpengine/platform-flywheel diff --git a/rootfs/etc/nginx/lua/balancer.lua b/rootfs/etc/nginx/lua/balancer.lua index 2c6a83ae9f..e4380ad401 100644 --- a/rootfs/etc/nginx/lua/balancer.lua +++ b/rootfs/etc/nginx/lua/balancer.lua @@ -168,6 +168,11 @@ local function sync_backends() backends_with_external_name[backend_with_external_name.name] = backend_with_external_name else sync_backend(new_backend) + -- If backends_with_external_name contains this backend, remove it. + -- Otherwise cached backend will be used. + if backends_with_external_name[new_backend.name] then + backends_with_external_name[new_backend.name] = nil + end end balancers_to_keep[new_backend.name] = true end @@ -363,12 +368,17 @@ function _M.log() balancer:after_balance() end +function _M.get_backends_with_external_name() + return util.deepcopy(backends_with_external_name) +end + setmetatable(_M, {__index = { get_implementation = get_implementation, sync_backend = sync_backend, route_to_alternative_balancer = route_to_alternative_balancer, get_balancer = get_balancer, get_balancer_by_upstream_name = get_balancer_by_upstream_name, + sync_backends = sync_backends, }}) return _M diff --git a/rootfs/etc/nginx/lua/test/balancer_test.lua b/rootfs/etc/nginx/lua/test/balancer_test.lua index 2d42ad3306..6d7b3c774f 100644 --- a/rootfs/etc/nginx/lua/test/balancer_test.lua +++ b/rootfs/etc/nginx/lua/test/balancer_test.lua @@ -532,5 +532,92 @@ describe("Balancer", function() assert.not_equal(balancer.get_balancer(), nil) end) + it("sync backends nothing to remove from backends_with_external_name only example-com should exist", function() + backends = { + { + name = "example-com", service = { spec = { ["type"] = "ExternalName" } }, + endpoints = { + { address = "example.com", port = "80", maxFails = 0, failTimeout = 0 } + } + }, + { + name = "access-router-production-web-80", port = "80", secure = false, + sslPassthrough = false, + endpoints = { + { address = "10.184.7.40", port = "8080", maxFails = 0, failTimeout = 0 }, + { address = "10.184.97.100", port = "8080", maxFails = 0, failTimeout = 0 }, + { address = "10.184.98.239", port = "8080", maxFails = 0, failTimeout = 0 }, + } + } + } + + mock_ngx({ var = { proxy_upstream_name = "access-router-production-web-80" }, ctx = { } }, function() + ngx.shared.configuration_data:set("backends", cjson.encode(backends)) + end) + + balancer.sync_backends() + local backends_with_external_name = balancer.get_backends_with_external_name() + local externals_count = 0 + for _ in pairs(backends_with_external_name) do externals_count = externals_count + 1 end + local expected_external_backend_count = 1 + assert.equal(expected_external_backend_count, externals_count) + + assert.are.same(backends[1], backends_with_external_name["example-com"]) + end) + + it("sync backends no external backends exist, should not interfere with non-external backends", function() + backends = { + { + name = "access-router-production-web-80", port = "80", secure = false, + sslPassthrough = false, + endpoints = { + { address = "10.184.7.40", port = "8080", maxFails = 0, failTimeout = 0 }, + { address = "10.184.97.100", port = "8080", maxFails = 0, failTimeout = 0 }, + { address = "10.184.98.239", port = "8080", maxFails = 0, failTimeout = 0 }, + } + } + } + + mock_ngx({ var = { proxy_upstream_name = "access-router-production-web-80" }, ctx = { } }, function() + ngx.shared.configuration_data:set("backends", cjson.encode(backends)) + end) + + balancer.sync_backends() + local backends_with_external_name = balancer.get_backends_with_external_name() + local externals_count = 0 + for _ in pairs(backends_with_external_name) do externals_count = externals_count + 1 end + local expected_external_backend_count = 0 + assert.equal(expected_external_backend_count, externals_count) + end) + + it("sync backends ensure last external backend is used backend backends_with_external_name", function() + backends = { + { + name = "example-com", service = { spec = { ["type"] = "ExternalName" } }, + endpoints = { + { address = "example.com", port = "80", maxFails = 0, failTimeout = 0 } + } + }, + { + name = "example-com", service = { spec = { ["type"] = "ExternalName" } }, + endpoints = { + { address = "example2.com", port = "80", maxFails = 0, failTimeout = 0 } + } + } + } + + mock_ngx({ var = { proxy_upstream_name = "access-router-production-web-80" }, ctx = { } }, function() + ngx.shared.configuration_data:set("backends", cjson.encode(backends)) + end) + + balancer.sync_backends() + local backends_with_external_name = balancer.get_backends_with_external_name() + local externals_count = 0 + for _ in pairs(backends_with_external_name) do externals_count = externals_count + 1 end + local expected_external_backend_count = 1 + assert.equal(expected_external_backend_count, externals_count) + assert.are.same(backends[2], backends_with_external_name["example-com"]) + end) + end) end)