From da1ac6013ffc0503c02403607632e2400435385a Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Wed, 11 Mar 2015 18:51:31 -0700 Subject: [PATCH] feat: #68 migrate keyspace if it doesn't exist. Instead of doing this in the bash script, we do it in main.lua ini_by_lua since the error handling from bin/kong is already handled. We only run migrations if we detect than they wer enever ran before. We won't automatically run any new migration because the process shouldn't be transparent, users should know about it and backup their data if they want to. --- bin/kong | 15 +-------------- src/kong/dao/cassandra/base_dao.lua | 1 - src/kong/dao/cassandra/factory.lua | 16 ++++++++-------- src/kong/tools/migrations.lua | 2 +- src/main.lua | 19 ++++++++++++++++--- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/bin/kong b/bin/kong index 6cecd6b1bd2..18039be8b64 100755 --- a/bin/kong +++ b/bin/kong @@ -55,7 +55,7 @@ function print_start_error { ############## function show_help { - printf "Usage: kong [OPTION]... {start|stop|restart|migrate}\n + printf "Usage: kong [OPTION]... {start|stop|restart}\n \t-c specify the path to a custom Kong configuration file \t default is: '$KONG_HOME/kong.yml' \t-v output version informations and exit @@ -65,7 +65,6 @@ function show_help { \tstop stop a running Kong \trestart restart Kong \t it is equivalent to executing 'stop' and 'start' in succession -\tmigrate performs a database migration, execute this operation carefully \tversion output version informations and exit \n" } @@ -107,15 +106,6 @@ function start { fi } -function migrate { - $KONG_HOME/scripts/db.lua -c $KONG_CONF migrate - if [ $? -eq 0 ]; then - exit 0 - else - exit 1 - fi -} - function stop { printf "Stopping Kong" @@ -173,9 +163,6 @@ case "$@" in restart) restart ;; - migrate) - migrate - ;; version) show_version ;; diff --git a/src/kong/dao/cassandra/base_dao.lua b/src/kong/dao/cassandra/base_dao.lua index e9c280b7f80..817020b5542 100644 --- a/src/kong/dao/cassandra/base_dao.lua +++ b/src/kong/dao/cassandra/base_dao.lua @@ -34,7 +34,6 @@ end -- Since this method only accepts an ordered list, we build this list from -- the `params` property of all prepared statement, taking into account special -- cassandra values (uuid, timestamps, NULL) --- -- @param {table} schema A schema with type properties to encode specific values -- @param {table} t Values to bind to a statement -- @param {table} parameters An ordered list of parameters diff --git a/src/kong/dao/cassandra/factory.lua b/src/kong/dao/cassandra/factory.lua index 38270ca62f7..8a88e7aa01e 100644 --- a/src/kong/dao/cassandra/factory.lua +++ b/src/kong/dao/cassandra/factory.lua @@ -58,16 +58,15 @@ end -- Prepare all statements in collection._queries and put them in collection._statements. -- Should be called with only a collection and will recursively call itself for nested statements. --- -- @param collection A collection with a ._queries property -local function prepare(collection, queries, statements) +local function prepare_collection(collection, queries, statements) if not queries then queries = collection._queries end if not statements then statements = collection._statements end for stmt_name, query in pairs(queries) do if type(query) == "table" and query.query == nil then collection._statements[stmt_name] = {} - prepare(collection, query, collection._statements[stmt_name]) + prepare_collection(collection, query, collection._statements[stmt_name]) else local q = stringy.strip(query.query) q = string.format(q, "") @@ -88,7 +87,7 @@ function CassandraFactory:prepare() self.plugins, self.accounts, self.applications }) do - local err = prepare(collection) + local err = prepare_collection(collection) if err then return err end @@ -97,7 +96,6 @@ end -- Execute a string of queries separated by ; -- Useful for huge DDL operations such as migrations --- -- @param {string} queries Semicolon separated string of queries -- @param {boolean} no_keyspace Won't set the keyspace if true -- @return {string} error if any @@ -180,15 +178,17 @@ end -- @return A list of previously executed migration (as strings) -- @return error if any function CassandraFactory:get_migrations() - local keyspace, err = self:execute("SELECT * FROM schema_keyspaces WHERE keyspace_name = ?", { self._properties.keyspace }, "system") + local rows, err + + rows, err = self:execute("SELECT * FROM schema_keyspaces WHERE keyspace_name = ?", { self._properties.keyspace }, "system") if err then return nil, err - elseif #keyspace == 0 then + elseif #rows == 0 then -- keyspace is not yet created, this is the first migration return nil end - local rows, err = self:execute("SELECT migrations FROM schema_migrations WHERE id = ?", { MIGRATION_IDENTIFIER }) + rows, err = self:execute("SELECT migrations FROM schema_migrations WHERE id = ?", { MIGRATION_IDENTIFIER }) if err then return nil, err elseif rows and #rows > 0 then diff --git a/src/kong/tools/migrations.lua b/src/kong/tools/migrations.lua index 3f4c9cb482a..3cc59baf35f 100644 --- a/src/kong/tools/migrations.lua +++ b/src/kong/tools/migrations.lua @@ -136,7 +136,7 @@ function Migrations:rollback(callback) if not migration_to_rollback.init then local _, err = self.dao:delete_migration(migration_to_rollback.name) if err then - callback(migration_to_rollback, "Cannot delete migration "..migration_to_rollback.name..": "..err) -- avoid a luacheck warning if calling cb directly here + callback(migration_to_rollback, "Cannot delete migration "..migration_to_rollback.name..": "..err) return end end diff --git a/src/main.lua b/src/main.lua index 2cc02b0bbfc..6bac66623e9 100644 --- a/src/main.lua +++ b/src/main.lua @@ -62,8 +62,6 @@ local function load_plugin_conf(api_id, application_id, plugin_name) end local function init_plugins() - -- Initializing plugins - plugins_available = configuration.plugins_available and configuration.plugins_available or {} print("Discovering used plugins. Please wait..") @@ -126,10 +124,25 @@ function _M.init() -- Loading configuration configuration, dao = utils.load_configuration_and_dao(os.getenv("KONG_CONF")) + -- Detect if keyspace is set + local keyspace, err = dao:get_migrations() + if err then + error(err) + elseif keyspace == nil then + -- No previous migrations, it should be safe to run them + print("Database not initialized. Running migrations...") + local migrations = require("kong.tools.migrations")(dao) + migrations:migrate(function(migration, err) + if err then + error(err) + end + end) + end + -- Initializing DAO local err = dao:prepare() if err then - error("Cannot prepare Cassandra statements: "..err.message) + error("Cannot prepare statements: "..err.message) end -- Initializing plugins