Krang Upgrade System

This document describes the Krang upgrade system for developers. If you just want to upgrade Krang, see Upgrade.

Introduction

Krang provides an upgrade system to allow existing Krang installations to use new code without losing data and configuration. When you make changes to Krang you may need to add commands to an upgrade module. This document will show you how.

Automatic Code Upgrades

The only thing that Krang does automatically is overwrite old source files with new source files. For example, if you fix a bug in lib/Krang/Story.pm and the fix doesn't require a database update then your work is almost certainly done.

Database Upgrades

If you make a change to the DB schema, or the contents of the database then you need to add code to affect that change during the upgrade. For example, let's say I've added a new property for stories called 'foo_id'. That will naturally require a new column in the story table, which I will add to story.sql:

  foo_id      INT UNSIGNED NOT NULL,

That's fine for new installations, which will use story.sql to construct the story table, but for upgrades I need to make that change to the live database. To do so I add a line to the per_instance() subroutine in the upgrade module for this release, upgrade/V0_022.pm:

  sub per_instance {
      my $self = shift;
      my $dbh = dbh();
      # add the foo_id column
      $dbh->do("ALTER TABLE story ADD COLUMN foo_id INT UNSIGNED NOT NULL");
  }

If an upgrade module for the current version doesn't exist yet just copy an older one and use it as a template. For more details, see Krang::Upgrade.

Data Changes

Krang does nothing with the data/ directory during upgrade unless you write code to do it. If you make a change to how files are stored under data/ then you'll need to add code to make the change.

For example, lets say I decided to rename the directory storing addon details from addons/ to addon-db/. I would add code to the per_installation() method in upgrade module:

  sub per_installation {
      my $self = shift;
      # rename data/addons to data/addon-db
      system("mv", catdir(KrangRoot, 'data', 'addons'),
                   catdir(KrangRoot, 'data', 'addon-db'));
  }

This is done in per_installation() rather than per_instance() because it should be done once during install, not once for each instance.

Other Changes

Virtually any change you can write can be accomodated by the upgrade module. Just decide whether the change requires per-instance activity or per-installation and put your code in the proper method.

How Krang Uses Upgrade Modules

When Krang is running an upgrade it determines which upgrade modules to run by looking at the source and target versions. For example, to upgrade from v1.001 to v1.004 Krang would run, if available:

   upgrade/V1_002.pm
   upgrade/V1_003.pm
   upgrade/V1_004.pm

How to Run an Upgrade Module Manually

While testing upgrade modules it helps to be able to run them by hand, rather than as part of a full krang_upgrade run. Here's how it's done, using V1_000.pm as an example:

   KRANG_ROOT=`pwd` perl -Ilib -Iupgrade -MKrang::Script \
   -MV1_000 -e 'V1_000->new()->upgrade()'