From c94f8a716d6ce7569e9eaa0ec6a473c13317c31b Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Fri, 26 Jun 2015 18:44:14 +0200 Subject: [PATCH] fix(migrations) handle missing schema_migrations Handle occasional error where the schema_migrations columnfamily would be missing thus preventing the migrations to work properly. We now print a better error for the unaware user and suggest that the "kong migrations reset" command should be run to fix this. Fix #250 Former-commit-id: 4e62f5f36fd20dc029a92f2f54e88a372879ad06 --- kong-0.4.0-1.rockspec | 1 + kong/cli/migrations.lua | 25 +++++++++++++------------ kong/cli/utils/input.lua | 24 ++++++++++++++++++++++++ kong/dao/cassandra/migrations.lua | 12 +++++++++++- kong/tools/migrations.lua | 14 -------------- 5 files changed, 49 insertions(+), 27 deletions(-) create mode 100644 kong/cli/utils/input.lua diff --git a/kong-0.4.0-1.rockspec b/kong-0.4.0-1.rockspec index 201fe10d8535..901f59944750 100644 --- a/kong-0.4.0-1.rockspec +++ b/kong-0.4.0-1.rockspec @@ -44,6 +44,7 @@ build = { ["kong.cli.utils"] = "kong/cli/utils/utils.lua", ["kong.cli.utils.signal"] = "kong/cli/utils/signal.lua", + ["kong.cli.utils.input"] = "kong/cli/utils/input.lua", ["kong.cli.db"] = "kong/cli/db.lua", ["kong.cli.config"] = "kong/cli/config.lua", ["kong.cli.quit"] = "kong/cli/quit.lua", diff --git a/kong/cli/migrations.lua b/kong/cli/migrations.lua index 8dcd95c3ae7f..c3fb208e2cb9 100644 --- a/kong/cli/migrations.lua +++ b/kong/cli/migrations.lua @@ -3,8 +3,9 @@ local Migrations = require "kong.tools.migrations" local constants = require "kong.constants" local cutils = require "kong.cli.utils" +local input = require "kong.cli.utils.input" local IO = require "kong.tools.io" -local lapp = require("lapp") +local lapp = require "lapp" local args = lapp(string.format([[ Kong datastore migrations. @@ -50,7 +51,7 @@ if args.command == "list" then elseif args.command == "up" then cutils.logger:info(string.format( - "Migrating %s keyspace: %s", + "Migrating %s keyspace \"%s\"", cutils.colors.yellow(dao_factory.type), cutils.colors.yellow(dao_factory._properties.keyspace)) ) @@ -68,7 +69,7 @@ elseif args.command == "up" then elseif args.command == "down" then cutils.logger:info(string.format( - "Rolling back %s keyspace: %s", + "Rollbacking %s keyspace \"%s\"", cutils.colors.yellow(dao_factory.type), cutils.colors.yellow(dao_factory._properties.keyspace) )) @@ -85,22 +86,22 @@ elseif args.command == "down" then elseif args.command == "reset" then + local keyspace = dao_factory._properties.keyspace + cutils.logger:info(string.format( - "Reseting %s keyspace: %s", + "Resetting %s keyspace \"%s\"", cutils.colors.yellow(dao_factory.type), - cutils.colors.yellow(dao_factory._properties.keyspace)) - ) + cutils.colors.yellow(keyspace) + )) - migrations:reset(function(migration, err) + if input.confirm("Are you sure? You will lose all of your data, this operation is irreversible.") then + local res, err = dao_factory.migrations:drop_keyspace(keyspace) if err then cutils.logger:error_exit(err) - elseif migration then - cutils.logger:success("Rollbacked: "..cutils.colors.yellow(migration.name)) else - cutils.logger:success("Schema reseted") + cutils.logger:success("Keyspace successfully reset") end - end) - + end else lapp.quit("Invalid command: "..args.command) end diff --git a/kong/cli/utils/input.lua b/kong/cli/utils/input.lua new file mode 100644 index 000000000000..47dec7a59471 --- /dev/null +++ b/kong/cli/utils/input.lua @@ -0,0 +1,24 @@ +local _M = {} + +local ANSWERS = { + y = true, + Y = true, + yes = true, + YES = true, + n = false, + N = false, + no = false, + NO = false +} + +function _M.confirm(question) + local answer + repeat + io.write(question.." [Y/n] ") + answer = ANSWERS[io.read("*l")] + until answer ~= nil + + return answer +end + +return _M diff --git a/kong/dao/cassandra/migrations.lua b/kong/dao/cassandra/migrations.lua index 00971dc88ff8..c62a4986535b 100644 --- a/kong/dao/cassandra/migrations.lua +++ b/kong/dao/cassandra/migrations.lua @@ -1,4 +1,5 @@ local cassandra = require "cassandra" +local stringy = require "stringy" local BaseDao = require "kong.dao.cassandra.base_dao" local Migrations = BaseDao:extend() @@ -48,7 +49,9 @@ function Migrations:get_migrations() end rows, err = Migrations.super._execute(self, self.queries.get_migrations) - if err then + if err and stringy.find(err.message, "unconfigured columnfamily schema_migrations") ~= nil then + return nil, "Missing mandatory column family \"schema_migrations\" in configured keyspace. Please consider running \"kong migrations reset\" to fix this." + elseif err then return nil, err elseif rows and #rows > 0 then return rows[1].migrations @@ -63,6 +66,13 @@ function Migrations:delete_migration(migration_name) { cassandra.list({ migration_name }) }) end +-- Drop the entire keyspace +-- @param `keyspace` Name of the keyspace to drop +-- @return query result +function Migrations:drop_keyspace(keyspace) + return Migrations.super._execute(self, string.format("DROP keyspace \"%s\"", keyspace)) +end + function Migrations:drop() -- never drop this end diff --git a/kong/tools/migrations.lua b/kong/tools/migrations.lua index 341c61ac3e2f..c9bc9c5c21f3 100644 --- a/kong/tools/migrations.lua +++ b/kong/tools/migrations.lua @@ -153,18 +153,4 @@ function Migrations:rollback(callback) callback(migration_to_rollback) end --- Execute all migrations DOWN --- @param {function} callback A function to execute on each migration (ie: for logging) -function Migrations:reset(callback) - local done = false - while not done do - self:rollback(function(migration, err) - if not migration and not err then - done = true - end - callback(migration, err) - end) - end -end - return Migrations