summaryrefslogtreecommitdiffstats
path: root/playbooks/common/openshift-cluster/upgrades/library/openshift_upgrade_config.py
blob: 673f11889c25a955211d0cda404226a21e46af61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/python
# -*- coding: utf-8 -*-
# vim: expandtab:tabstop=4:shiftwidth=4

"""Ansible module for modifying OpenShift configs during an upgrade"""

import os
import yaml

DOCUMENTATION = '''
---
module: openshift_upgrade_config
short_description: OpenShift Upgrade Config
author: Jason DeTiberus
requirements: [ ]
'''
EXAMPLES = '''
'''


def modify_api_levels(level_list, remove, ensure, msg_prepend='',
                      msg_append=''):
    """ modify_api_levels """
    changed = False
    changes = []

    if not isinstance(remove, list):
        remove = []

    if not isinstance(ensure, list):
        ensure = []

    if not isinstance(level_list, list):
        new_list = []
        changed = True
        changes.append("%s created missing %s" % (msg_prepend, msg_append))
    else:
        new_list = level_list
        for level in remove:
            if level in new_list:
                new_list.remove(level)
                changed = True
                changes.append("%s removed %s %s" % (msg_prepend, level, msg_append))

    for level in ensure:
        if level not in new_list:
            new_list.append(level)
            changed = True
            changes.append("%s added %s %s" % (msg_prepend, level, msg_append))

    return {'new_list': new_list, 'changed': changed, 'changes': changes}


def upgrade_master_3_0_to_3_1(ansible_module, config_base, backup):
    """Main upgrade method for 3.0 to 3.1."""
    changes = []

    # Facts do not get transferred to the hosts where custom modules run,
    # need to make some assumptions here.
    master_config = os.path.join(config_base, 'master/master-config.yaml')

    master_cfg_file = open(master_config, 'r')
    config = yaml.safe_load(master_cfg_file.read())
    master_cfg_file.close()

    # Remove unsupported api versions and ensure supported api versions from
    # master config
    unsupported_levels = ['v1beta1', 'v1beta2', 'v1beta3']
    supported_levels = ['v1']

    result = modify_api_levels(config.get('apiLevels'), unsupported_levels,
                               supported_levels, 'master-config.yaml:', 'from apiLevels')
    if result['changed']:
        config['apiLevels'] = result['new_list']
        changes.append(result['changes'])

    if 'kubernetesMasterConfig' in config and 'apiLevels' in config['kubernetesMasterConfig']:
        config['kubernetesMasterConfig'].pop('apiLevels')
        changes.append('master-config.yaml: removed kubernetesMasterConfig.apiLevels')

    # Add masterCA to serviceAccountConfig
    if 'serviceAccountConfig' in config and 'masterCA' not in config['serviceAccountConfig']:
        config['serviceAccountConfig']['masterCA'] = config['oauthConfig'].get('masterCA', 'ca.crt')

    # Add proxyClientInfo to master-config
    if 'proxyClientInfo' not in config['kubernetesMasterConfig']:
        config['kubernetesMasterConfig']['proxyClientInfo'] = {
            'certFile': 'master.proxy-client.crt',
            'keyFile': 'master.proxy-client.key'
        }
        changes.append("master-config.yaml: added proxyClientInfo")

    if len(changes) > 0:
        if backup:
            # TODO: Check success:
            ansible_module.backup_local(master_config)

        # Write the modified config:
        out_file = open(master_config, 'w')
        out_file.write(yaml.safe_dump(config, default_flow_style=False))
        out_file.close()

    return changes


def upgrade_master(ansible_module, config_base, from_version, to_version, backup):
    """Upgrade entry point."""
    if from_version == '3.0':
        if to_version == '3.1':
            return upgrade_master_3_0_to_3_1(ansible_module, config_base, backup)


def main():
    """ main """
    # disabling pylint errors for global-variable-undefined and invalid-name
    # for 'global module' usage, since it is required to use ansible_facts
    # pylint: disable=global-variable-undefined, invalid-name,
    # redefined-outer-name
    global module

    module = AnsibleModule(  # noqa: F405
        argument_spec=dict(
            config_base=dict(required=True),
            from_version=dict(required=True, choices=['3.0']),
            to_version=dict(required=True, choices=['3.1']),
            role=dict(required=True, choices=['master']),
            backup=dict(required=False, default=True, type='bool')
        ),
        supports_check_mode=True,
    )

    from_version = module.params['from_version']
    to_version = module.params['to_version']
    role = module.params['role']
    backup = module.params['backup']
    config_base = module.params['config_base']

    try:
        changes = []
        if role == 'master':
            changes = upgrade_master(module, config_base, from_version,
                                     to_version, backup)

        changed = len(changes) > 0
        return module.exit_json(changed=changed, changes=changes)

    # ignore broad-except error to avoid stack trace to ansible user
    # pylint: disable=broad-except
    except Exception as e:
        return module.fail_json(msg=str(e))


# ignore pylint errors related to the module_utils import
# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, wrong-import-position
# import module snippets
from ansible.module_utils.basic import *  # noqa: E402,F403

if __name__ == '__main__':
    main()