This repository has been archived on 2023-05-06. You can view files and clone it, but cannot push or open issues or pull requests.
pleroma-ansible-playbook/library/compare_semantic_versions.py
Dan Anglin c9aad82027
fix: implement an upgrade procedure for Pleroma.
This commit implements different installation paths when
running the pleroma-main role, depending on whether Pleroma
needs to be installed for the first time or upgraded.

For first time installations the playbook will run through
the normal download and installation process and also executes
the database migration. If Pleroma is already installed then,
by default, the playbook will not re-install Pleroma or re-run
the database migration. If the user wants to update Pleroma to
a newer version then they can re-run the playbook with the
command-line argument '--extra-vars enable_pleroma_upgrade=True'.

This commit also introduces a custom module used to compare the
installed and downloaded semantic versions of Pleroma.
The playbook uses this to see whether the version change is an upgrade,
a downgrade or no version change. If it's an upgrade the playbook
will proceed with the re-installation of Pleroma. If there is no
change then the playbook will skip installation. Finally if
it detects that the user is trying to downgrade Pleroma then it will
fail.

This commit resolves dananglin/pleroma-ansible-playbook#9 and also
resolves dananglin/pleroma-ansible-playbook#5
2020-03-06 12:04:48 +00:00

162 lines
4 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright: (c) 2020, Daniel Anglin <d.n.i.anglin@gmail.com>
# The MIT License (see LICENSE or https://mit-license.org)
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'supported_by': 'community',
'status': ['preview']
}
DOCUMENTATION = '''
---
module: compare_semantic_versions
short_description: Compares two semantic version values.
description:
- This module compares two semantic versions and outputs whether the change is an upgrade, a downgrade or no change.
- The values must use valid semantic versioning in order for a successful comparison.
version_added: "2.9.5"
author: Daniel Anglin (@dananglin)
options:
new_version:
description:
- The semantic version of the new software.
required: true
type: string
old_version:
description:
- The semantic version of the old software.
required: true
type: string
'''
EXAMPLES = '''
- name: Simple comparison between two semantic versions.
compare_semantic_versions:
old_version: "1.7.10"
new_version: "1.8.0"
register: output1
- debug:
msg: "{{ output1.result }}"
- name: Semantic versions with the 'v' prefix are supported.
compare_semantic_versions:
old_version: "1.6.7"
new_version: "v3.5.9"
register: output2
- debug:
msg: "{{ output2.result }}"
- name: Semantic versions without minor and/or patch versions are supported.
compare_semantic_versions:
old_version: "v1.100.3"
new_version: "v2"
register: output3
- debug:
msg: "{{ output3.result }}"
'''
RETURN = '''
result:
description:
- The result of the comparison between the two semantic versions.
- The value "upgrade" is returned if the new version is higher than the old version.
- The value "downgrade" is returned if the new version is lower than the old version.
- The value "noVersionChange" is returned if the new version equals the old version.
returned: On success
type: string
sample: upgrade
'''
from ansible.module_utils.basic import AnsibleModule
UPGRADE = "upgrade"
DOWNGRADE = "downgrade"
NO_VERSION_CHANGE = "noVersionChange"
MAJOR = "major"
MINOR = "minor"
PATCH = "patch"
MAX_VERSION_COMPONENTS = 3
def process(semVer):
if semVer.startswith('v'):
semVer = semVer[1:]
semVerArr = semVer.split(".")
if len(semVerArr) > MAX_VERSION_COMPONENTS:
raise ValueError("invalid number of version components in semantic version '{}'.".format(semVer))
if len(semVerArr) < MAX_VERSION_COMPONENTS:
diff = MAX_VERSION_COMPONENTS - len(semVerArr)
for i in range(diff):
semVerArr.append('0')
try:
semVerMap = {
MAJOR: int(semVerArr[0]),
MINOR: int(semVerArr[1]),
PATCH: int(semVerArr[2])
}
except ValueError as e:
raise ValueError("unable to parse an int for semantic version '{}' due to invalid format. ({})".format(semVer, str(e)))
return semVerMap
def compare_versions(old, new):
try:
oldSemVerMap = process(old)
newSemVerMap = process(new)
except:
raise
versions = [MAJOR, MINOR, PATCH]
for v in range(len(versions)):
if newSemVerMap[versions[v]] > oldSemVerMap[versions[v]]:
return UPGRADE
elif newSemVerMap[versions[v]] < oldSemVerMap[versions[v]]:
return DOWNGRADE
return NO_VERSION_CHANGE
def run_module():
module_args = dict(
new_version = dict(type='str', required=True),
old_version = dict(type='str', required=True)
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
output = dict(
changed=False,
result=''
)
try:
result = compare_versions(module.params['old_version'], module.params['new_version'])
except ValueError as e:
module.fail_json(msg="Unable to compare semantic versions: {}".format(str(e)), **output)
output['result'] = result
module.exit_json(**output)
def main():
run_module()
if __name__ == '__main__':
main()