balena-supervisor/src/db.coffee

34 lines
851 B
CoffeeScript
Raw Normal View History

2014-03-19 19:17:07 +00:00
Knex = require 'knex'
path = require 'path'
DB, Config: Implement modules to interact with the sqlite DB and to manage configuration These modules allow managing the models in the sqlite database and the configuration for the supervisor. The database will now have a schema version, and the supervisor will normalize any legacy data when migrating from an older schema (i.e. when doing a supervisor update). This will make model changes cleaner. If a migration is needed, the DB initialization will return "true" and store the legacy data in a legacyData table. Once the supervisor finishes migrating the data, it calls `db.finishMigration` to mark the migration complete and clear the legacyData table. Changes in the models: * The database implements the tables for multicontainer applications that now have services, networks and volumes as in a docker compose file. * Dependent apps and devices now have separate tables to store their target states. * The deviceConfig table now only stores target values, as the current ones will be inferred from the state of the device. * We keep a table for images as we have no way to label them in docker storage, so we need to keep our own track of what images are relevant for the supervisor. The Config object allows transparent management of configuration values, mainly through `get`, `getMany` and `set` functions. The values can be stored in config.json or the database, and this is managed with a schema definition that also defines whether values are mutable and whether they have default values. Some configuration values are of the "func" type, which means that instead of corresponding to a config.json or database key, they result from a helper function that aggregates other configuration values or gets the value from other sources, like OS version and supervisor version. Writes to config.json are atomic if a path to the file via /mnt/root can be found. We keep a write-through cache of the file to avoid unnecessary IO. Changelog-Entry: Implement the multicontainer app models, and change the supervisor configuration management to avoid duplication between fields in config.json and fields in the internal database Change-Type: patch Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-11-01 07:10:55 +00:00
constants = require './lib/constants'
module.exports = class DB
constructor: ({ @databasePath } = {}) ->
@databasePath ?= constants.databasePath
@knex = Knex(
client: 'sqlite3'
connection:
filename: @databasePath
useNullAsDefault: true
)
init: =>
@knex('knex_migrations_lock').update({ is_locked: 0 })
.catch(->) # Knex doesn't return a bluebird promise here so we can't catchReturn :(
.then =>
@knex.migrate.latest(directory: path.join(__dirname, 'migrations'))
DB, Config: Implement modules to interact with the sqlite DB and to manage configuration These modules allow managing the models in the sqlite database and the configuration for the supervisor. The database will now have a schema version, and the supervisor will normalize any legacy data when migrating from an older schema (i.e. when doing a supervisor update). This will make model changes cleaner. If a migration is needed, the DB initialization will return "true" and store the legacy data in a legacyData table. Once the supervisor finishes migrating the data, it calls `db.finishMigration` to mark the migration complete and clear the legacyData table. Changes in the models: * The database implements the tables for multicontainer applications that now have services, networks and volumes as in a docker compose file. * Dependent apps and devices now have separate tables to store their target states. * The deviceConfig table now only stores target values, as the current ones will be inferred from the state of the device. * We keep a table for images as we have no way to label them in docker storage, so we need to keep our own track of what images are relevant for the supervisor. The Config object allows transparent management of configuration values, mainly through `get`, `getMany` and `set` functions. The values can be stored in config.json or the database, and this is managed with a schema definition that also defines whether values are mutable and whether they have default values. Some configuration values are of the "func" type, which means that instead of corresponding to a config.json or database key, they result from a helper function that aggregates other configuration values or gets the value from other sources, like OS version and supervisor version. Writes to config.json are atomic if a path to the file via /mnt/root can be found. We keep a write-through cache of the file to avoid unnecessary IO. Changelog-Entry: Implement the multicontainer app models, and change the supervisor configuration management to avoid duplication between fields in config.json and fields in the internal database Change-Type: patch Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-11-01 07:10:55 +00:00
# Returns a knex object for one of the models (tables)
models: (modelName) =>
@knex(modelName)
upsertModel: (modelName, obj, id, trx) =>
knex = trx ? @knex
knex(modelName).update(obj).where(id)
.then (n) ->
if n == 0
knex(modelName).insert(obj)
DB, Config: Implement modules to interact with the sqlite DB and to manage configuration These modules allow managing the models in the sqlite database and the configuration for the supervisor. The database will now have a schema version, and the supervisor will normalize any legacy data when migrating from an older schema (i.e. when doing a supervisor update). This will make model changes cleaner. If a migration is needed, the DB initialization will return "true" and store the legacy data in a legacyData table. Once the supervisor finishes migrating the data, it calls `db.finishMigration` to mark the migration complete and clear the legacyData table. Changes in the models: * The database implements the tables for multicontainer applications that now have services, networks and volumes as in a docker compose file. * Dependent apps and devices now have separate tables to store their target states. * The deviceConfig table now only stores target values, as the current ones will be inferred from the state of the device. * We keep a table for images as we have no way to label them in docker storage, so we need to keep our own track of what images are relevant for the supervisor. The Config object allows transparent management of configuration values, mainly through `get`, `getMany` and `set` functions. The values can be stored in config.json or the database, and this is managed with a schema definition that also defines whether values are mutable and whether they have default values. Some configuration values are of the "func" type, which means that instead of corresponding to a config.json or database key, they result from a helper function that aggregates other configuration values or gets the value from other sources, like OS version and supervisor version. Writes to config.json are atomic if a path to the file via /mnt/root can be found. We keep a write-through cache of the file to avoid unnecessary IO. Changelog-Entry: Implement the multicontainer app models, and change the supervisor configuration management to avoid duplication between fields in config.json and fields in the internal database Change-Type: patch Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-11-01 07:10:55 +00:00
transaction: (cb) =>
@knex.transaction(cb)