From b7aa2ca869340afe96e11528740730f1a6d741ee Mon Sep 17 00:00:00 2001 From: Yaroslav Dynnikov Date: Thu, 6 May 2021 18:40:08 +0300 Subject: [PATCH] Store schema example in the clusterwide config If one applies an empty schema using the 'ddl-manager' role API, put in the clusterwide configuration an example instead. --- CHANGELOG.md | 5 ++++ cartridge/roles/ddl-manager.lua | 49 +++++++++++++++++++-------------- test/db.lua | 1 + test/role_test.lua | 8 +++--- test/set_schema_test.lua | 30 +++++++++++++++++--- 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 267b393..badbcce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/cartridge/roles/ddl-manager.lua b/cartridge/roles/ddl-manager.lua index 3f6ceec..778a0f7 100644 --- a/cartridge/roles/ddl-manager.lua +++ b/cartridge/roles/ddl-manager.lua @@ -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') @@ -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: @@ -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 @@ -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 @@ -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. @@ -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 = {}} @@ -151,7 +160,7 @@ 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' .. @@ -159,7 +168,7 @@ local function set_clusterwide_schema_yaml(schema_yml) ) error(err, 2) else - patch = {[_section_name] = schema_yml} + patch = {[vars._section_name] = schema_yml} end return cartridge.config_patch_clusterwide(patch) @@ -175,7 +184,7 @@ 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' .. @@ -183,7 +192,7 @@ local function set_clusterwide_schema_lua(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) @@ -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, diff --git a/test/db.lua b/test/db.lua index fe6f9a2..4b9fa76 100644 --- a/test/db.lua +++ b/test/db.lua @@ -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') diff --git a/test/role_test.lua b/test/role_test.lua index 887713b..edd988f 100644 --- a/test/role_test.lua +++ b/test/role_test.lua @@ -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 @@ -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 = ' ' @@ -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' @@ -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 = {} diff --git a/test/set_schema_test.lua b/test/set_schema_test.lua index e2dda0e..5da409a 100644 --- a/test/set_schema_test.lua +++ b/test/set_schema_test.lua @@ -638,6 +638,17 @@ 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', @@ -645,9 +656,7 @@ function g.test_path() 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, { @@ -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', @@ -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({