#!/usr/bin/env python3
# WARNING: If importing this fails set PYTHONPATH.
import yaml
import ansible
import subprocess
from os import path, environ
from packaging import version

SCRIPT_DIR = path.dirname(path.realpath(__file__))
# Where Ansible looks for installed roles.
ANSIBLE_ROLES_PATH = path.join(environ['HOME'], '.ansible/roles')


class Role:
    def __init__(self, name, version):
        self.name = name
        self.version = version

    @property
    def path(self):
        return path.join(ANSIBLE_ROLES_PATH, self.name)
    
    def exists(self):
        return path.isdir(self.path)

    def local_version(self):
        cmd = subprocess.run(
            ['git', 'rev-parse', 'HEAD'],
            capture_output=True,
            cwd=self.path
        )
        cmd.check_returncode()
        return str(cmd.stdout.strip(), 'utf-8')


# Verify Ansible version is 2.8 or newer.
if version.parse(ansible.__version__) < version.parse("2.8"):
    print('Your Ansible version is lower than 2.8. Upgrade it.')
    exit(1)

# Read Ansible requirements file.
with open(path.join(SCRIPT_DIR, 'requirements.yml'), 'r') as f:
    requirements = yaml.load(f, Loader=yaml.FullLoader)

# Check if each Ansible role is installed and has correct version.
errors = 0
for req in requirements:
    role = Role(req['name'], req.get('version'))

    if not role.exists():
        print('%25s - MISSING!' % role.name)
        errors += 1
        continue

    # For now we allow not specifying versions for everyhing.
    if role.version is None:
        print('%25s - No version!' % role.name)
        continue

    local_version = role.local_version()
    if role.version != local_version:
        print('%25s - MISMATCH: %s != %s' %
              (role.name, role.version[:8], local_version[:8]))
        errors += 1
        continue

    print('%25s - VALID' % role.name)

# Any issue with any role should cause failure.
if errors > 0:
    exit(1)