Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Changed

- If one applies an empty schema using the 'ddl-manager' role API,
put in the clusterwide configuration an example instead.

## [1.4.0] - 2021-04-22

### Added
Expand Down
49 changes: 29 additions & 20 deletions cartridge/roles/ddl-manager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ local yaml = require('yaml').new()
local errors = require('errors')

local cartridge = require('cartridge')
local twophase = require('cartridge.twophase')
local failover = require('cartridge.failover')
local vars = require('cartridge.vars').new('cartridge.roles.ddl-manager')

vars:new('on_patch_trigger', nil)
vars:new('_section_name', nil)
vars:new('_example_schema', nil)

local CheckSchemaError = errors.new_class('CheckSchemaError')

Expand All @@ -14,8 +20,8 @@ yaml.cfg({
decode_save_metatables = false,
})

local _section_name = 'schema.yml'
local _example_schema = [[## Example:
vars._section_name = 'schema.yml'
vars._example_schema = [[## Example:
#
# spaces:
# customer:
Expand Down Expand Up @@ -47,12 +53,23 @@ local _example_schema = [[## Example:
# - {path: fullname, type: string, is_nullable: false}
]]

-- Be gentle with cartridge.reload_roles
twophase.on_patch(nil, vars.on_patch_trigger)
function vars.on_patch_trigger(conf_new)
local schema_yml = conf_new:get_readonly(vars._section_name)

if schema_yml == nil or schema_yml == '' then
conf_new:set_plaintext(vars._section_name, vars._example_schema)
end
end
twophase.on_patch(vars.on_patch_trigger, nil)

local function apply_config(conf, opts)
if not opts.is_master then
return true
end

local schema_yml = conf[_section_name]
local schema_yml = conf[vars._section_name]
if schema_yml == nil then
return true
end
Expand All @@ -69,7 +86,7 @@ local function apply_config(conf, opts)
end

local function validate_config(conf_new, _)
local schema_yml = conf_new[_section_name]
local schema_yml = conf_new[vars._section_name]
if schema_yml == nil then
return true
end
Expand Down Expand Up @@ -111,18 +128,10 @@ end

--- Get clusterwide schema as a YAML string.
--
-- In case there's no schema set, return a commented out example.
--
-- @function get_clusterwide_schema_yaml
-- @treturn string yaml-encoded schema
local function get_clusterwide_schema_yaml()
local schema_yml = cartridge.config_get_readonly(_section_name)

if schema_yml == nil or schema_yml == '' then
return _example_schema
else
return schema_yml
end
return cartridge.config_get_readonly(vars._section_name)
end

--- Get clusterwide schema as a Lua table.
Expand All @@ -132,7 +141,7 @@ end
-- @function get_clusterwide_schema_lua
-- @treturn table schema
local function get_clusterwide_schema_lua()
local schema_yml = cartridge.config_get_readonly(_section_name)
local schema_yml = cartridge.config_get_readonly(vars._section_name)
local schema_lua = schema_yml and yaml.decode(schema_yml)
if schema_lua == nil then
return {spaces = {}}
Expand All @@ -151,15 +160,15 @@ end
local function set_clusterwide_schema_yaml(schema_yml)
local patch
if schema_yml == nil then
patch = {[_section_name] = box.NULL}
patch = {[vars._section_name] = box.NULL}
elseif type(schema_yml) ~= 'string' then
local err = string.format(
'Bad argument #1 to set_clusterwide_schema_yaml' ..
' (?string expected, got %s)', type(schema_yml)
)
error(err, 2)
else
patch = {[_section_name] = schema_yml}
patch = {[vars._section_name] = schema_yml}
end

return cartridge.config_patch_clusterwide(patch)
Expand All @@ -175,15 +184,15 @@ end
local function set_clusterwide_schema_lua(schema_lua)
local patch
if schema_lua == nil then
patch = {[_section_name] = box.NULL}
patch = {[vars._section_name] = box.NULL}
elseif type(schema_lua) ~= 'table' then
local err = string.format(
'Bad argument #1 to set_clusterwide_schema_lua' ..
' (?table expected, got %s)', type(schema_lua)
)
error(err, 2)
else
patch = {[_section_name] = yaml.encode(schema_lua)}
patch = {[vars._section_name] = yaml.encode(schema_lua)}
end

return cartridge.config_patch_clusterwide(patch)
Expand Down Expand Up @@ -267,8 +276,8 @@ end
return {
role_name = 'ddl-manager',
permanent = true,
_section_name = _section_name,
_example_schema = _example_schema,
_section_name = vars._section_name,
_example_schema = vars._example_schema,

init = init,
stop = stop,
Expand Down
1 change: 1 addition & 0 deletions test/db.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ local function drop_all()
end
end

-- Check if tarantool version >= required
local function v(req_major, req_minor)
req_minor = req_minor or 0
assert(type(req_major) == 'number')
Expand Down
8 changes: 4 additions & 4 deletions test/role_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function g.test_yaml()

t.assert_str_matches(call('get_clusterwide_schema_yaml'), '## Example:\n.+')
t.assert_equals(call('get_clusterwide_schema_lua'), {spaces = {}})
t.assert_equals(get_section(), '')
t.assert_equals(call('get_clusterwide_schema_yaml'), get_section())

--------------------------------------------------------------------
local schema = nil
Expand All @@ -81,7 +81,7 @@ function g.test_yaml()

t.assert_str_matches(call('get_clusterwide_schema_yaml'), '## Example:\n.+')
t.assert_equals(call('get_clusterwide_schema_lua'), {spaces = {}})
t.assert_equals(get_section(), nil)
t.assert_equals(call('get_clusterwide_schema_yaml'), get_section())

--------------------------------------------------------------------
local schema = ' '
Expand All @@ -103,7 +103,7 @@ function g.test_yaml()

t.assert_str_matches(call('get_clusterwide_schema_yaml'), '## Example:\n.+')
t.assert_equals(call('get_clusterwide_schema_lua'), {spaces = {}})
t.assert_equals(get_section(), nil)
t.assert_equals(call('get_clusterwide_schema_yaml'), get_section())

--------------------------------------------------------------------
local schema = 'null'
Expand Down Expand Up @@ -269,7 +269,7 @@ function g.test_lua()

t.assert_equals(call('get_clusterwide_schema_lua'), {spaces = {}})
t.assert_str_matches(call('get_clusterwide_schema_yaml'), '## Example:\n.+')
t.assert_equals(get_section(), nil)
t.assert_equals(call('get_clusterwide_schema_yaml'), get_section())

--------------------------------------------------------------------
local schema = {}
Expand Down
30 changes: 26 additions & 4 deletions test/set_schema_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -638,16 +638,25 @@ function g.test_path()
}
})

local error_expected
if db.v(2, 8) then
-- See: https://github.com/tarantool/tarantool/issues/4707
error_expected = 'spaces["test"].indexes["path_idx"]:' ..
" Field 1 (unsigned_nonnull) has type 'unsigned' in one index," ..
" but type 'map' in another"
else
error_expected = 'spaces["test"].indexes["path_idx"]:' ..
" Field 1 has type 'unsigned' in one index," ..
" but type 'map' in another"
end
_test_index({
{
name = 'path_idx',
type = 'TREE',
unique = true,
parts = {{path = 'unsigned_nonnull.DATA["name"]', type = 'unsigned', is_nullable = false}}
}},
[[spaces["test"].indexes["path_idx"]: Field 1 has type 'unsigned' in one index, but type 'map' in another]]
-- [[spaces["test"].indexes["path_idx"].parts[1].path: path (unsigned_nonnull.DATA["name"])]] ..
-- [[ is json_path. It references to field[unsigned_nonnull] with type unsigned, but expected map]]
error_expected
)

_test_index({pk, {
Expand Down Expand Up @@ -718,6 +727,19 @@ function g.test_multikey_path()
}
}})



local error_expected
if db.v(2, 8) then
-- See: https://github.com/tarantool/tarantool/issues/4707
error_expected = 'spaces["test"].indexes["path_idx"]:' ..
" Field 15 (map_nonnull) has type 'map' in one index," ..
" but type 'array' in another"
else
error_expected = 'spaces["test"].indexes["path_idx"]:' ..
" Field 15 has type 'map' in one index," ..
" but type 'array' in another"
end
_test_index({pk, {
name = 'path_idx',
type = 'TREE',
Expand All @@ -729,7 +751,7 @@ function g.test_multikey_path()
}
}
}},
[[spaces["test"].indexes["path_idx"]: Field 15 has type 'map' in one index, but type 'array' in another]]
error_expected
)

_test_index({
Expand Down