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

163 lines
4 KiB
Python
Raw Normal View History

#!/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()