kong/spec/01-unit/01-db/01-schema/11-declarative_config/04-on-the-fly-migration_spec.lua (137 lines of code) (raw):

require("spec.helpers") -- for kong.log local declarative = require "kong.db.declarative" local conf_loader = require "kong.conf_loader" local null = ngx.null local helpers = require "spec.helpers" local tablex = require "pl.tablex" local utils = require "kong.tools.utils" local function sort_by_key(t) return function(a, b) for _, k in ipairs({"name", "username", "host", "scope"}) do local ka = t[a][k] ~= null and t[a][k] local kb = t[b][k] ~= null and t[b][k] if ka and kb then return ka < kb end end end end local function sortedpairs(t, fn) local ks = tablex.keys(t) table.sort(ks, fn and fn(t)) local i = 0 return function() i = i + 1 return ks[i], t[ks[i]] end end assert:set_parameter("TableFormatLevel", 10) local function idempotent(tbl, err) assert.table(tbl, err) for entity, items in sortedpairs(tbl) do local new = {} for _, item in sortedpairs(items, sort_by_key) do table.insert(new, item) end tbl[entity] = new end local function recurse_fields(t) helpers.deep_sort(t) for k,v in sortedpairs(t) do if k == "id" and utils.is_valid_uuid(v) then t[k] = "UUID" end if k == "client_id" or k == "client_secret" or k == "access_token" then t[k] = "RANDOM" end if type(v) == "table" then recurse_fields(v) end if k == "created_at" or k == "updated_at" then t[k] = 1234567890 end end end recurse_fields(tbl) table.sort(tbl) return tbl end describe("declarative config: on the fly migration", function() for _, format_verion in ipairs{"1.1", "2.1", "3.0"} do it("routes handling for format version " .. format_verion, function() local dc = assert(declarative.new_config(conf_loader())) local configs = { [[ _format_version: "]] .. format_verion .. [[" services: - name: foo host: example.com protocol: https enabled: false _comment: my comment _ignore: - foo: bar - name: bar host: example.test port: 3000 _comment: my comment _ignore: - foo: bar tags: [hello, world] routes: - name: foo path_handling: v0 protocols: ["https"] paths: ["/regex.+", "/prefix" ] snis: - "example.com" service: foo ]], [[ _format_version: "]] .. format_verion .. [[" services: - name: foo host: example.com protocol: https enabled: false _comment: my comment _ignore: - foo: bar routes: - name: foo path_handling: v0 protocols: ["https"] paths: ["/regex.+", "/prefix" ] snis: - "example.com" - name: bar host: example.test port: 3000 _comment: my comment _ignore: - foo: bar tags: [hello, world] ]], } for _, config in ipairs(configs) do local config_tbl = assert(dc:parse_string(config)) local sorted = idempotent(config_tbl) assert.same("bar", sorted.services[1].name) assert.same("example.test", sorted.services[1].host) assert.same("http", sorted.services[1].protocol) assert.same(3000, sorted.services[1].port) assert.same("foo", sorted.services[2].name) assert.same("example.com", sorted.services[2].host) assert.same("https", sorted.services[2].protocol) assert.same(false, sorted.services[2].enabled) assert.same("foo", sorted.routes[1].name) assert.same({"https"}, sorted.routes[1].protocols) if format_verion == "3.0" then assert.same({ "/prefix", "/regex.+", }, sorted.routes[1].paths) else assert.same({ "/prefix", "~/regex.+", }, sorted.routes[1].paths) end end end) end end)