Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

👌 IMPROVE: Configuration migrations #5319

Merged
merged 14 commits into from
Jan 21, 2022

Conversation

chrisjsewell
Copy link
Member

Allow for both upgrades and downgrades, and expose this in the CLI.

This will allow a route for user to downgrade their configuration,
if they try a new version of aiida, but then want to return to an old version.

Allow for both upgrades and downgrades, and expose this in the CLI.

This will allow a route for user to downgrade their configuration,
if they try a new version of aiida, but then want to return to an old version.
@chrisjsewell
Copy link
Member Author

I haven't added tests for the CLI commands yet @sphuber; will do if you agree they make sense in general

Note, this is a prelude to adding a migration, to "compartmentalize" config required by a backend (AIIDADB_NAME, etc) to a "storage" key

@chrisjsewell chrisjsewell changed the title 👌 IMPROVE: Configuration migration 👌 IMPROVE: Configuration migrations Jan 19, 2022
@codecov
Copy link

codecov bot commented Jan 19, 2022

Codecov Report

Merging #5319 (e34d041) into develop (4cf9d93) will increase coverage by 0.03%.
The diff coverage is 94.64%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5319      +/-   ##
===========================================
+ Coverage    82.11%   82.13%   +0.03%     
===========================================
  Files          534      533       -1     
  Lines        38398    38480      +82     
===========================================
+ Hits         31526    31603      +77     
- Misses        6872     6877       +5     
Flag Coverage Δ
django 77.22% <94.64%> (+0.04%) ⬆️
sqlalchemy 76.51% <94.64%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
aiida/manage/__init__.py 100.00% <ø> (ø)
aiida/manage/configuration/__init__.py 83.60% <ø> (ø)
aiida/manage/configuration/migrations/__init__.py 100.00% <ø> (ø)
...iida/manage/configuration/migrations/migrations.py 94.25% <94.08%> (+0.63%) ⬆️
aiida/cmdline/commands/cmd_config.py 92.75% <100.00%> (+0.86%) ⬆️
aiida/manage/configuration/config.py 89.18% <100.00%> (ø)
aiida/transports/plugins/local.py 81.46% <0.00%> (-0.25%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4cf9d93...e34d041. Read the comment docs.

@sphuber
Copy link
Contributor

sphuber commented Jan 19, 2022

Cheers @chrisjsewell , guess my first question would be what the advantage is of having this a manual operation? Why shouldn't we just do this automatically? Is the reason because certain downgrades may be lossy? But even in that case, if they want to downgrade, they are forced to migrate anyway, and there will be an automatic backup. So maybe an automatic migration is still the easiest for users?

@chrisjsewell
Copy link
Member Author

@sphuber how can you automatically downgrade using an old version of aiida, that does not have that migration available 😬
The only way to downgrade, is to use the version of aiida, that has the upgrade. Unless I'm missing something

@sphuber
Copy link
Contributor

sphuber commented Jan 19, 2022

@sphuber how can you automatically downgrade using an old version of aiida, that does not have that migration available grimacing The only way to downgrade, is to use the version of aiida, that has the upgrade. Unless I'm missing something

I thought the goal of the downgrade was the following scenario:

  • User has aiida-core==1.0 with config v1 installed
  • User upgrades to aiida-core==2.0 which has config v2. Currently, this is automatically upgraded.
  • User downgrades again to aiida-core==1.0 and now AiiDA will say the config is not compatible

I thought that your description described this scenario, and this would now allow the user to call verdi config downgrade to make their config file compatible again. But my question is whether that should be a manual action or whether we should simply automatically downgrade to the compatible version, just as we upgrade it manually. Why would a user ever want to manually down or upgrade to a version that then won't be compatible with the installation anyway?

Edit: nevermind, I just got the point. Ok, so then we should provide clear instructions (which we can now only do in v2.0 or we need to backport it to v1.6 as well) that in order to downgrade, a more recent version of AiiDA should be installed and then call verdi config downgrade VERSION.

@chrisjsewell
Copy link
Member Author

User downgrades again to aiida-core==1.0 and now AiiDA will say the config is not compatible

But how can aiida-core v1 downgrade from a future version?

@chrisjsewell
Copy link
Member Author

Edit: nevermind, I just got the point...

Yep 👍

@sphuber
Copy link
Contributor

sphuber commented Jan 19, 2022

One major problem that I see with all this is that in order to really try a new version of AiiDA, they will have to migrate their database and those are not downgradable, so there is no point in downgrading the config because you won't be able to use the profile anyway.

But I guess, the config can hold more than one profile, and non-migrated profiles could then at least still be used again with an older installation. So maybe this can still be useful. Think just that it should be clearly documented that people should not expect to be able to freely move back and forth between versions. Once you move forward and migrate (both config and storage) you are most likely going to be stuck with that version.

@chrisjsewell
Copy link
Member Author

What if you upgrade and create a new profile, then want to downgrade and use an older (unmigrated) profile?

@sphuber
Copy link
Contributor

sphuber commented Jan 20, 2022

What if you upgrade and create a new profile, then want to downgrade and use an older (unmigrated) profile?

Fair. I guess that there are some niche use cases, so I am fine with moving forward with this. Just think we should be very clear up front that the fact that this is here, it isn't possible to always arbitrarily migrate back and forth. Will now review the rest of the PR.

@click.option('--version', type=int, default=None, help='Upgrade to specific version (default current).')
def verdi_config_upgrade(version, path):
"""Print a configuration, upgraded to a specific version."""
from aiida.manage.configuration import CURRENT_CONFIG_VERSION, get_config_path, upgrade_config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this the explicit default in the option, or is aiida.manage one of the modules we cannot import top-level because of loading time?



@verdi_config.command('upgrade')
@click.argument('path', required=False, default=None, type=click.Path(exists=True, path_type=Path))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want this to be configurable? There should always be just a single config.json per instance, shouldn't there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think I will remove this command since, on calling the command, verdi is already auto-upgrading, rendering it kinda useless.
The main thing is the downgrad command

aiida/cmdline/commands/cmd_config.py Outdated Show resolved Hide resolved
aiida/manage/configuration/migrations/migrations.py Outdated Show resolved Hide resolved
aiida/manage/configuration/migrations/migrations.py Outdated Show resolved Hide resolved
config.setdefault('CONFIG_VERSION', {})['OLDEST_COMPATIBLE'] = 0

def downgrade(self, config: ConfigType) -> None:
config.setdefault('CONFIG_VERSION', {})['OLDEST_COMPATIBLE'] = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the downgrade not remove these keys, since they were added in the upgrade?

from uuid import uuid4 # we require this import here, to patch it in the tests
for profile in config.get('profiles', {}).values():
profile.setdefault('PROFILE_UUID', uuid4().hex)
config.setdefault('CONFIG_VERSION', {})['OLDEST_COMPATIBLE'] = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this line necessary? That is from the previous migration no?

aiida/manage/configuration/migrations/migrations.py Outdated Show resolved Hide resolved

def downgrade(self, config: ConfigType) -> None:
config.setdefault('CONFIG_VERSION', {})['OLDEST_COMPATIBLE'] = 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this is not really a downgrade since it does not undo the upgrade. Could this cause issues if actually loading the downgrade config with an older version of aiida-core?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, a downgrade is not to "undo an upgrade", it is to make it compliant with the lower versions schema.

As mentioned above, in #5320, I have also removed the fact that Profile strips unknown keys.
I think there may even be an open issue about this: someone inadvertently used an older version of aiida, which stripped these keys, then tried to upgrade again and it was no longer working

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, happy to go ahead with that behavior if it will be guaranteed to work and we assume that behavior from now on

aiida/manage/configuration/migrations/migrations.py Outdated Show resolved Hide resolved
@chrisjsewell
Copy link
Member Author

it isn't possible to always arbitrarily migrate back and forth

why though? I don't see any reason why not

@chrisjsewell
Copy link
Member Author

I think I've answered all your comments @sphuber, there is just the outstanding issue of the verdi config downgrade functionality+testing, will wait on your comments first though

@sphuber
Copy link
Contributor

sphuber commented Jan 20, 2022

why though? I don't see any reason why not

Maybe in theory it could be possible, but it is not clear that we always can. The config may be more lenient with allowing additional keys, and so having downgrades not being a full undo of an upgrade, but to me it is not clear that with the PostgreSQL database we have the same luxury. Besides, it would mean an even greater development load by forcing us to implement and test the downgrade of each migration, which would also be non-trivial. In any case, the majority of migrations at this moment don't have downgrades, so those would have to be written first. But I really don't think we should go down this road.

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Jan 20, 2022

the majority of migrations at this moment don't have downgrades

well, I'd not all of the sqlalchemy migrations have at least some form of downgrade, which we rely on for the migration testing (you have to migrate down, before you can migrate up)

but no I'm not suggesting we put much more effort into supporting this

@chrisjsewell
Copy link
Member Author

Ok this should be good to go @sphuber


@verdi_config.command('downgrade')
@click.argument('version', type=int)
@click.option(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I am wrong, but I don't think you answered my question yet why we need the option to specify an arbitrary input and output file. Since this is user facing it should simply always operate on the currently configured config file. I would suggest to remove this additional complexity since I don't think it is needed for now and you don't have tests for it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed



@verdi_config.command('downgrade')
@click.argument('version', type=int)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this a type=click.Choice and get the available numbers dynamically from the available migrations? That would make it a lot better from a UI perspective.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@sphuber sphuber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @chrisjsewell . I am approving so we can merge this, but I did still wanted to note that because the writing of the config in the downgrade command now goes outside of the Config class, there will be no automatic backup created. Maybe this is something we want to add in the future to prevent losing a configuration if the downgrade were to ever be incorrect.

@chrisjsewell chrisjsewell merged commit 472bff5 into aiidateam:develop Jan 21, 2022
@chrisjsewell chrisjsewell deleted the storage-config branch January 21, 2022 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants