diff options
Diffstat (limited to 'roles')
39 files changed, 965 insertions, 239 deletions
diff --git a/roles/cockpit-ui/tasks/main.yml b/roles/cockpit-ui/tasks/main.yml index 8bd68787a..0114498f8 100644 --- a/roles/cockpit-ui/tasks/main.yml +++ b/roles/cockpit-ui/tasks/main.yml @@ -1,13 +1,16 @@  ---  - block: -  - name: Create passthrough route for docker-registry + +  # When openshift_hosted_manage_registry=true the openshift_hosted +  # role will create the appropriate route for the docker-registry. +  # When openshift_hosted_manage_registry=false then this code will +  # not be run. +  - name: fetch the docker-registry route      oc_route:        kubeconfig: "{{ openshift_master_config_dir }}/admin.kubeconfig"        name: docker-registry        namespace: default -      service_name: docker-registry -      state: present -      tls_termination: passthrough +      state: list      register: docker_registry_route    - name: Create passthrough route for registry-console @@ -41,7 +44,7 @@        {% if openshift_cockpit_deployer_prefix is defined  %}-p IMAGE_PREFIX="{{ openshift_cockpit_deployer_prefix }}"{% endif %}        {% if openshift_cockpit_deployer_version is defined  %}-p IMAGE_VERSION="{{ openshift_cockpit_deployer_version }}"{% endif %}        -p OPENSHIFT_OAUTH_PROVIDER_URL="{{ openshift.master.public_api_url }}" -      -p REGISTRY_HOST="{{ docker_registry_route.results.results[0].spec.host }}" +      -p REGISTRY_HOST="{{ docker_registry_route.results[0].spec.host }}"        -p COCKPIT_KUBE_URL="https://{{ registry_console_cockpit_kube.results.results[0].spec.host }}"        --config={{ openshift_hosted_kubeconfig }}        -n default diff --git a/roles/lib_openshift/library/oc_adm_ca_server_cert.py b/roles/lib_openshift/library/oc_adm_ca_server_cert.py index c69f5deda..4d083c4d5 100644 --- a/roles/lib_openshift/library/oc_adm_ca_server_cert.py +++ b/roles/lib_openshift/library/oc_adm_ca_server_cert.py @@ -1508,7 +1508,7 @@ class CAServerCert(OpenShiftCLI):          x509output, _ = proc.communicate()          if proc.returncode == 0:              regex = re.compile(r"^\s*X509v3 Subject Alternative Name:\s*?\n\s*(.*)\s*\n", re.MULTILINE) -            match = regex.search(x509output)  # E501 +            match = regex.search(x509output.decode())  # E501              if not match:                  return False diff --git a/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py b/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py index f954f40ef..cf99a6584 100644 --- a/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py +++ b/roles/lib_openshift/src/class/oc_adm_ca_server_cert.py @@ -77,7 +77,7 @@ class CAServerCert(OpenShiftCLI):          x509output, _ = proc.communicate()          if proc.returncode == 0:              regex = re.compile(r"^\s*X509v3 Subject Alternative Name:\s*?\n\s*(.*)\s*\n", re.MULTILINE) -            match = regex.search(x509output)  # E501 +            match = regex.search(x509output.decode())  # E501              if not match:                  return False diff --git a/roles/openshift_health_checker/library/aos_version.py b/roles/openshift_health_checker/library/aos_version.py index 191a4b107..a46589443 100755 --- a/roles/openshift_health_checker/library/aos_version.py +++ b/roles/openshift_health_checker/library/aos_version.py @@ -1,91 +1,199 @@  #!/usr/bin/python  # vim: expandtab:tabstop=4:shiftwidth=4  ''' -Ansible module for determining if multiple versions of an OpenShift package are -available, and if the version requested is available down to the given -precision. - -Multiple versions available suggest that multiple repos are enabled for the -different versions, which may cause installation problems. +Ansible module for yum-based systems determining if multiple releases +of an OpenShift package are available, and if the release requested +(if any) is available down to the given precision. + +For Enterprise, multiple releases available suggest that multiple repos +are enabled for the different releases, which may cause installation +problems. With Origin, however, this is a normal state of affairs as +all the releases are provided in a single repo with the expectation that +only the latest can be installed. + +Code in the openshift_version role contains a lot of logic to pin down +the exact package and image version to use and so does some validation +of release availability already. Without duplicating all that, we would +like the user to have a helpful error message if we detect things will +not work out right. Note that if openshift_release is not specified in +the inventory, the version comparison checks just pass. + +TODO: fail gracefully on non-yum systems (dnf in Fedora)  ''' -import yum  # pylint: disable=import-error -  from ansible.module_utils.basic import AnsibleModule +IMPORT_EXCEPTION = None +try: +    import yum  # pylint: disable=import-error +except ImportError as err: +    IMPORT_EXCEPTION = err  # in tox test env, yum import fails + -def main():  # pylint: disable=missing-docstring,too-many-branches +class AosVersionException(Exception): +    '''Base exception class for package version problems''' +    def __init__(self, message, problem_pkgs=None): +        Exception.__init__(self, message) +        self.problem_pkgs = problem_pkgs + + +def main(): +    '''Entrypoint for this Ansible module'''      module = AnsibleModule(          argument_spec=dict( -            prefix=dict(required=True),  # atomic-openshift, origin, ... -            version=dict(required=True), +            requested_openshift_release=dict(type="str", default=''), +            openshift_deployment_type=dict(required=True), +            rpm_prefix=dict(required=True),  # atomic-openshift, origin, ...?          ),          supports_check_mode=True      ) -    def bail(error):  # pylint: disable=missing-docstring -        module.fail_json(msg=error) - -    rpm_prefix = module.params['prefix'] +    if IMPORT_EXCEPTION: +        module.fail_json(msg="aos_version module could not import yum: %s" % IMPORT_EXCEPTION) +    # determine the packages we will look for +    rpm_prefix = module.params['rpm_prefix']      if not rpm_prefix: -        bail("prefix must not be empty") - -    yb = yum.YumBase()  # pylint: disable=invalid-name -    yb.conf.disable_excludes = ["all"]  # assume the openshift excluder will be managed, ignore current state - -    # search for package versions available for aos pkgs -    expected_pkgs = [ +        module.fail_json(msg="rpm_prefix must not be empty") +    expected_pkgs = set([          rpm_prefix,          rpm_prefix + '-master',          rpm_prefix + '-node', -    ] +    ]) + +    # determine what level of precision the user specified for the openshift version. +    # should look like a version string with possibly many segments e.g. "3.4.1": +    requested_openshift_release = module.params['requested_openshift_release'] + +    # get the list of packages available and complain if anything is wrong +    try: +        pkgs = _retrieve_available_packages(expected_pkgs) +        if requested_openshift_release: +            _check_precise_version_found(pkgs, expected_pkgs, requested_openshift_release) +            _check_higher_version_found(pkgs, expected_pkgs, requested_openshift_release) +        if module.params['openshift_deployment_type'] in ['openshift-enterprise']: +            _check_multi_minor_release(pkgs, expected_pkgs) +    except AosVersionException as excinfo: +        module.fail_json(msg=str(excinfo)) +    module.exit_json(changed=False) + + +def _retrieve_available_packages(expected_pkgs): +    # search for package versions available for openshift pkgs +    yb = yum.YumBase()  # pylint: disable=invalid-name + +    # The openshift excluder prevents unintended updates to openshift +    # packages by setting yum excludes on those packages. See: +    # https://wiki.centos.org/SpecialInterestGroup/PaaS/OpenShift-Origin-Control-Updates +    # Excludes are then disabled during an install or upgrade, but +    # this check will most likely be running outside either. When we +    # attempt to determine what packages are available via yum they may +    # be excluded. So, for our purposes here, disable excludes to see +    # what will really be available during an install or upgrade. +    yb.conf.disable_excludes = ['all'] +      try:          pkgs = yb.pkgSack.returnPackages(patterns=expected_pkgs) -    except yum.Errors.PackageSackError as e:  # pylint: disable=invalid-name +    except yum.Errors.PackageSackError as excinfo:          # you only hit this if *none* of the packages are available -        bail('Unable to find any OpenShift packages.\nCheck your subscription and repo settings.\n%s' % e) +        raise AosVersionException('\n'.join([ +            'Unable to find any OpenShift packages.', +            'Check your subscription and repo settings.', +            str(excinfo), +        ])) +    return pkgs -    # determine what level of precision we're expecting for the version -    expected_version = module.params['version'] -    if expected_version.startswith('v'):  # v3.3 => 3.3 -        expected_version = expected_version[1:] -    num_dots = expected_version.count('.') -    pkgs_by_name_version = {} +class PreciseVersionNotFound(AosVersionException): +    '''Exception for reporting packages not available at given release''' +    def __init__(self, requested_release, not_found): +        msg = ['Not all of the required packages are available at requested version %s:' % requested_release] +        msg += ['  ' + name for name in not_found] +        msg += ['Please check your subscriptions and enabled repositories.'] +        AosVersionException.__init__(self, '\n'.join(msg), not_found) + + +def _check_precise_version_found(pkgs, expected_pkgs, requested_openshift_release): +    # see if any packages couldn't be found at requested release version +    # we would like to verify that the latest available pkgs have however specific a version is given. +    # so e.g. if there is a package version 3.4.1.5 the check passes; if only 3.4.0, it fails. +      pkgs_precise_version_found = {}      for pkg in pkgs: -        # get expected version precision -        match_version = '.'.join(pkg.version.split('.')[:num_dots + 1]) -        if match_version == expected_version: +        if pkg.name not in expected_pkgs: +            continue +        # does the version match, to the precision requested? +        # and, is it strictly greater, at the precision requested? +        match_version = '.'.join(pkg.version.split('.')[:requested_openshift_release.count('.') + 1]) +        if match_version == requested_openshift_release:              pkgs_precise_version_found[pkg.name] = True -        # get x.y version precision -        minor_version = '.'.join(pkg.version.split('.')[:2]) -        if pkg.name not in pkgs_by_name_version: -            pkgs_by_name_version[pkg.name] = {} -        pkgs_by_name_version[pkg.name][minor_version] = True -    # see if any packages couldn't be found at requested version -    # see if any packages are available in more than one minor version      not_found = [] -    multi_found = []      for name in expected_pkgs:          if name not in pkgs_precise_version_found:              not_found.append(name) + +    if not_found: +        raise PreciseVersionNotFound(requested_openshift_release, not_found) + + +class FoundHigherVersion(AosVersionException): +    '''Exception for reporting that a higher version than requested is available''' +    def __init__(self, requested_release, higher_found): +        msg = ['Some required package(s) are available at a version', +               'that is higher than requested %s:' % requested_release] +        msg += ['  ' + name for name in higher_found] +        msg += ['This will prevent installing the version you requested.'] +        msg += ['Please check your enabled repositories or adjust openshift_release.'] +        AosVersionException.__init__(self, '\n'.join(msg), higher_found) + + +def _check_higher_version_found(pkgs, expected_pkgs, requested_openshift_release): +    req_release_arr = [int(segment) for segment in requested_openshift_release.split(".")] +    # see if any packages are available in a version higher than requested +    higher_version_for_pkg = {} +    for pkg in pkgs: +        if pkg.name not in expected_pkgs: +            continue +        version = [int(segment) for segment in pkg.version.split(".")] +        too_high = version[:len(req_release_arr)] > req_release_arr +        higher_than_seen = version > higher_version_for_pkg.get(pkg.name, []) +        if too_high and higher_than_seen: +            higher_version_for_pkg[pkg.name] = version + +    if higher_version_for_pkg: +        higher_found = [] +        for name, version in higher_version_for_pkg.items(): +            higher_found.append(name + '-' + '.'.join(str(segment) for segment in version)) +        raise FoundHigherVersion(requested_openshift_release, higher_found) + + +class FoundMultiRelease(AosVersionException): +    '''Exception for reporting multiple minor releases found for same package''' +    def __init__(self, multi_found): +        msg = ['Multiple minor versions of these packages are available'] +        msg += ['  ' + name for name in multi_found] +        msg += ["There should only be one OpenShift release repository enabled at a time."] +        AosVersionException.__init__(self, '\n'.join(msg), multi_found) + + +def _check_multi_minor_release(pkgs, expected_pkgs): +    # see if any packages are available in more than one minor version +    pkgs_by_name_version = {} +    for pkg in pkgs: +        # keep track of x.y (minor release) versions seen +        minor_release = '.'.join(pkg.version.split('.')[:2]) +        if pkg.name not in pkgs_by_name_version: +            pkgs_by_name_version[pkg.name] = {} +        pkgs_by_name_version[pkg.name][minor_release] = True + +    multi_found = [] +    for name in expected_pkgs:          if name in pkgs_by_name_version and len(pkgs_by_name_version[name]) > 1:              multi_found.append(name) -    if not_found: -        msg = 'Not all of the required packages are available at requested version %s:\n' % expected_version -        for name in not_found: -            msg += '  %s\n' % name -        bail(msg + 'Please check your subscriptions and enabled repositories.') -    if multi_found: -        msg = 'Multiple minor versions of these packages are available\n' -        for name in multi_found: -            msg += '  %s\n' % name -        bail(msg + "There should only be one OpenShift version's repository enabled at a time.") -    module.exit_json(changed=False) +    if multi_found: +        raise FoundMultiRelease(multi_found)  if __name__ == '__main__': diff --git a/roles/openshift_health_checker/meta/main.yml b/roles/openshift_health_checker/meta/main.yml index 0bbeadd34..cd9b55902 100644 --- a/roles/openshift_health_checker/meta/main.yml +++ b/roles/openshift_health_checker/meta/main.yml @@ -1,3 +1,4 @@  ---  dependencies:    - role: openshift_facts +  - role: openshift_repos diff --git a/roles/openshift_health_checker/openshift_checks/package_availability.py b/roles/openshift_health_checker/openshift_checks/package_availability.py index 9891972a6..a7eb720fd 100644 --- a/roles/openshift_health_checker/openshift_checks/package_availability.py +++ b/roles/openshift_health_checker/openshift_checks/package_availability.py @@ -9,6 +9,10 @@ class PackageAvailability(NotContainerizedMixin, OpenShiftCheck):      name = "package_availability"      tags = ["preflight"] +    @classmethod +    def is_active(cls, task_vars): +        return super(PackageAvailability, cls).is_active(task_vars) and task_vars["ansible_pkg_mgr"] == "yum" +      def run(self, tmp, task_vars):          rpm_prefix = get_var(task_vars, "openshift", "common", "service_type")          group_names = get_var(task_vars, "group_names", default=[]) diff --git a/roles/openshift_health_checker/openshift_checks/package_version.py b/roles/openshift_health_checker/openshift_checks/package_version.py index e16c2d4c8..682f6bd40 100644 --- a/roles/openshift_health_checker/openshift_checks/package_version.py +++ b/roles/openshift_health_checker/openshift_checks/package_version.py @@ -17,11 +17,9 @@ class PackageVersion(NotContainerizedMixin, OpenShiftCheck):          return super(PackageVersion, cls).is_active(task_vars) and master_or_node      def run(self, tmp, task_vars): -        rpm_prefix = get_var(task_vars, "openshift", "common", "service_type") -        openshift_release = get_var(task_vars, "openshift_release") -          args = { -            "prefix": rpm_prefix, -            "version": openshift_release, +            "requested_openshift_release": get_var(task_vars, "openshift_release", default=''), +            "openshift_deployment_type": get_var(task_vars, "openshift_deployment_type"), +            "rpm_prefix": get_var(task_vars, "openshift", "common", "service_type"),          }          return self.execute_module("aos_version", args, tmp, task_vars) diff --git a/roles/openshift_health_checker/test/aos_version_test.py b/roles/openshift_health_checker/test/aos_version_test.py new file mode 100644 index 000000000..39c86067a --- /dev/null +++ b/roles/openshift_health_checker/test/aos_version_test.py @@ -0,0 +1,120 @@ +import pytest +import aos_version + +from collections import namedtuple +Package = namedtuple('Package', ['name', 'version']) + +expected_pkgs = set(['spam', 'eggs']) + + +@pytest.mark.parametrize('pkgs, requested_release, expect_not_found', [ +    ( +        [], +        '3.2.1', +        expected_pkgs,  # none found +    ), +    ( +        [Package('spam', '3.2.1')], +        '3.2', +        ['eggs'],  # completely missing +    ), +    ( +        [Package('spam', '3.2.1'), Package('eggs', '3.3.2')], +        '3.2', +        ['eggs'],  # not the right version +    ), +    ( +        [Package('spam', '3.2.1'), Package('eggs', '3.2.1')], +        '3.2', +        [],  # all found +    ), +    ( +        [Package('spam', '3.2.1'), Package('eggs', '3.2.1.5')], +        '3.2.1', +        [],  # found with more specific version +    ), +    ( +        [Package('eggs', '1.2.3'), Package('eggs', '3.2.1.5')], +        '3.2.1', +        ['spam'],  # eggs found with multiple versions +    ), +]) +def test_check_pkgs_for_precise_version(pkgs, requested_release, expect_not_found): +    if expect_not_found: +        with pytest.raises(aos_version.PreciseVersionNotFound) as e: +            aos_version._check_precise_version_found(pkgs, expected_pkgs, requested_release) +        assert set(expect_not_found) == set(e.value.problem_pkgs) +    else: +        aos_version._check_precise_version_found(pkgs, expected_pkgs, requested_release) + + +@pytest.mark.parametrize('pkgs, requested_release, expect_higher', [ +    ( +        [], +        '3.2.1', +        [], +    ), +    ( +        [Package('spam', '3.2.1')], +        '3.2', +        [],  # more precise but not strictly higher +    ), +    ( +        [Package('spam', '3.3')], +        '3.2.1', +        ['spam-3.3'],  # lower precision, but higher +    ), +    ( +        [Package('spam', '3.2.1'), Package('eggs', '3.3.2')], +        '3.2', +        ['eggs-3.3.2'],  # one too high +    ), +    ( +        [Package('eggs', '1.2.3'), Package('eggs', '3.2.1.5'), Package('eggs', '3.4')], +        '3.2.1', +        ['eggs-3.4'],  # multiple versions, one is higher +    ), +    ( +        [Package('eggs', '3.2.1'), Package('eggs', '3.4'), Package('eggs', '3.3')], +        '3.2.1', +        ['eggs-3.4'],  # multiple versions, two are higher +    ), +]) +def test_check_pkgs_for_greater_version(pkgs, requested_release, expect_higher): +    if expect_higher: +        with pytest.raises(aos_version.FoundHigherVersion) as e: +            aos_version._check_higher_version_found(pkgs, expected_pkgs, requested_release) +        assert set(expect_higher) == set(e.value.problem_pkgs) +    else: +        aos_version._check_higher_version_found(pkgs, expected_pkgs, requested_release) + + +@pytest.mark.parametrize('pkgs, expect_to_flag_pkgs', [ +    ( +        [], +        [], +    ), +    ( +        [Package('spam', '3.2.1')], +        [], +    ), +    ( +        [Package('spam', '3.2.1'), Package('eggs', '3.2.2')], +        [], +    ), +    ( +        [Package('spam', '3.2.1'), Package('spam', '3.3.2')], +        ['spam'], +    ), +    ( +        [Package('eggs', '1.2.3'), Package('eggs', '3.2.1.5'), Package('eggs', '3.4')], +        ['eggs'], +    ), +]) +def test_check_pkgs_for_multi_release(pkgs, expect_to_flag_pkgs): +    if expect_to_flag_pkgs: +        with pytest.raises(aos_version.FoundMultiRelease) as e: +            aos_version._check_multi_minor_release(pkgs, expected_pkgs) +        assert set(expect_to_flag_pkgs) == set(e.value.problem_pkgs) +    else: +        aos_version._check_multi_minor_release(pkgs, expected_pkgs) diff --git a/roles/openshift_health_checker/test/conftest.py b/roles/openshift_health_checker/test/conftest.py index d16401260..3cbd65507 100644 --- a/roles/openshift_health_checker/test/conftest.py +++ b/roles/openshift_health_checker/test/conftest.py @@ -6,5 +6,6 @@ import sys  openshift_health_checker_path = os.path.dirname(os.path.dirname(__file__))  sys.path[1:1] = [      openshift_health_checker_path, -    os.path.join(openshift_health_checker_path, 'action_plugins') +    os.path.join(openshift_health_checker_path, 'action_plugins'), +    os.path.join(openshift_health_checker_path, 'library'),  ] diff --git a/roles/openshift_health_checker/test/package_availability_test.py b/roles/openshift_health_checker/test/package_availability_test.py index 25385339a..f7e916a46 100644 --- a/roles/openshift_health_checker/test/package_availability_test.py +++ b/roles/openshift_health_checker/test/package_availability_test.py @@ -3,6 +3,20 @@ import pytest  from openshift_checks.package_availability import PackageAvailability +@pytest.mark.parametrize('pkg_mgr,is_containerized,is_active', [ +    ('yum', False, True), +    ('yum', True, False), +    ('dnf', True, False), +    ('dnf', False, False), +]) +def test_is_active(pkg_mgr, is_containerized, is_active): +    task_vars = dict( +        ansible_pkg_mgr=pkg_mgr, +        openshift=dict(common=dict(is_containerized=is_containerized)), +    ) +    assert PackageAvailability.is_active(task_vars=task_vars) == is_active + +  @pytest.mark.parametrize('task_vars,must_have_packages,must_not_have_packages', [      (          dict(openshift=dict(common=dict(service_type='openshift'))), diff --git a/roles/openshift_health_checker/test/package_version_test.py b/roles/openshift_health_checker/test/package_version_test.py index a2bdea729..196d9816a 100644 --- a/roles/openshift_health_checker/test/package_version_test.py +++ b/roles/openshift_health_checker/test/package_version_test.py @@ -6,16 +6,19 @@ from openshift_checks.package_version import PackageVersion  def test_package_version():      task_vars = dict(          openshift=dict(common=dict(service_type='origin')), -        openshift_release='v3.5', +        openshift_release='3.5', +        openshift_deployment_type='origin',      )      return_value = object()      def execute_module(module_name=None, module_args=None, tmp=None, task_vars=None):          assert module_name == 'aos_version' -        assert 'prefix' in module_args -        assert 'version' in module_args -        assert module_args['prefix'] == task_vars['openshift']['common']['service_type'] -        assert module_args['version'] == task_vars['openshift_release'] +        assert 'requested_openshift_release' in module_args +        assert 'openshift_deployment_type' in module_args +        assert 'rpm_prefix' in module_args +        assert module_args['requested_openshift_release'] == task_vars['openshift_release'] +        assert module_args['openshift_deployment_type'] == task_vars['openshift_deployment_type'] +        assert module_args['rpm_prefix'] == task_vars['openshift']['common']['service_type']          return return_value      check = PackageVersion(execute_module=execute_module) diff --git a/roles/openshift_metrics/files/import_jks_certs.sh b/roles/openshift_metrics/files/import_jks_certs.sh deleted file mode 100755 index f977b6dd6..000000000 --- a/roles/openshift_metrics/files/import_jks_certs.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -# -# Copyright 2014-2015 Red Hat, Inc. and/or its affiliates -# and other contributors as indicated by the @author tags. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -#    http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set -ex - -function import_certs() { -  dir=$CERT_DIR -  hawkular_metrics_keystore_password=$(echo $METRICS_KEYSTORE_PASSWD | base64 --decode) -  hawkular_metrics_truststore_password=$(echo $METRICS_TRUSTSTORE_PASSWD | base64 --decode) -  hawkular_alias=`keytool -noprompt -list -keystore $dir/hawkular-metrics.truststore -storepass ${hawkular_metrics_truststore_password} | sed -n '7~2s/,.*$//p'` - -  if [ ! -f $dir/hawkular-metrics.keystore ]; then -    echo "Creating the Hawkular Metrics keystore from the PEM file" -    keytool -importkeystore -v \ -      -srckeystore $dir/hawkular-metrics.pkcs12 \ -      -destkeystore $dir/hawkular-metrics.keystore \ -      -srcstoretype PKCS12 \ -      -deststoretype JKS \ -      -srcstorepass $hawkular_metrics_keystore_password \ -      -deststorepass $hawkular_metrics_keystore_password -  fi - -  cert_alias_names=(ca metricca) - -  for cert_alias in ${cert_alias_names[*]}; do -    if [[ ! ${hawkular_alias[*]} =~ "$cert_alias" ]]; then -      echo "Importing the CA Certificate with alias $cert_alias into the Hawkular Metrics Truststore" -      keytool -noprompt -import -v -trustcacerts -alias $cert_alias \ -        -file ${dir}/ca.crt \ -        -keystore $dir/hawkular-metrics.truststore \ -        -trustcacerts \ -        -storepass $hawkular_metrics_truststore_password -    fi -  done -} - -import_certs diff --git a/roles/openshift_metrics/tasks/generate_hawkular_certificates.yaml b/roles/openshift_metrics/tasks/generate_hawkular_certificates.yaml index 01fc1ef64..07b7eca33 100644 --- a/roles/openshift_metrics/tasks/generate_hawkular_certificates.yaml +++ b/roles/openshift_metrics/tasks/generate_hawkular_certificates.yaml @@ -13,21 +13,6 @@      hostnames: hawkular-cassandra    changed_when: no -- slurp: src={{ mktemp.stdout }}/hawkular-metrics-truststore.pwd -  register: hawkular_truststore_password - -- stat: path="{{mktemp.stdout}}/{{item}}" -  register: pwd_file_stat -  with_items: -  - hawkular-metrics.pwd -  - hawkular-metrics.htpasswd -  changed_when: no - -- set_fact: -    pwd_files: "{{pwd_files | default({}) | combine ({item.item: item.stat}) }}" -  with_items: "{{pwd_file_stat.results}}" -  changed_when: no -  - name: generate password for hawkular metrics    local_action: copy dest="{{ local_tmp.stdout}}/{{ item }}.pwd" content="{{ 15 | oo_random_word }}"    with_items: @@ -47,8 +32,6 @@    - hawkular-metrics.pwd    - hawkular-metrics.htpasswd -- include: import_jks_certs.yaml -  - name: read files for the hawkular-metrics secret    shell: >      printf '%s: ' '{{ item }}' @@ -56,13 +39,11 @@    register: hawkular_secrets    with_items:    - ca.crt -  - hawkular-metrics.crt -  - hawkular-metrics.keystore -  - hawkular-metrics-keystore.pwd -  - hawkular-metrics.truststore -  - hawkular-metrics-truststore.pwd    - hawkular-metrics.pwd    - hawkular-metrics.htpasswd +  - hawkular-metrics.crt +  - hawkular-metrics.key +  - hawkular-metrics.pem    - hawkular-cassandra.crt    - hawkular-cassandra.key    - hawkular-cassandra.pem @@ -73,42 +54,23 @@        {{ hawkular_secrets.results|map(attribute='stdout')|join('        ')|from_yaml }} -- name: generate hawkular-metrics-secrets secret template -  template: -    src: secret.j2 -    dest: "{{ mktemp.stdout }}/templates/hawkular_metrics_secrets.yaml" -  vars: -    name: hawkular-metrics-secrets -    labels: -      metrics-infra: hawkular-metrics -    data: -      hawkular-metrics.keystore: > -        {{ hawkular_secrets['hawkular-metrics.keystore'] }} -      hawkular-metrics.keystore.password: > -        {{ hawkular_secrets['hawkular-metrics-keystore.pwd'] }} -      hawkular-metrics.truststore: > -        {{ hawkular_secrets['hawkular-metrics.truststore'] }} -      hawkular-metrics.truststore.password: > -        {{ hawkular_secrets['hawkular-metrics-truststore.pwd'] }} -      hawkular-metrics.keystore.alias: "{{ 'hawkular-metrics'|b64encode }}" -      hawkular-metrics.htpasswd.file: > -        {{ hawkular_secrets['hawkular-metrics.htpasswd'] }} -  when: name not in metrics_secrets.stdout_lines -  changed_when: no - -- name: generate hawkular-metrics-certificate secret template +- name: generate hawkular-metrics-certs secret template    template:      src: secret.j2 -    dest: "{{ mktemp.stdout }}/templates/hawkular_metrics_certificate.yaml" +    dest: "{{ mktemp.stdout }}/templates/hawkular-metrics-certs.yaml"    vars: -    name: hawkular-metrics-certificate +    name: hawkular-metrics-certs      labels: -      metrics-infra: hawkular-metrics +      metrics-infra: hawkular-metrics-certs +    annotations: +      service.alpha.openshift.io/originating-service-name: hawkular-metrics      data: -      hawkular-metrics.certificate: > +      tls.crt: >          {{ hawkular_secrets['hawkular-metrics.crt'] }} -      hawkular-metrics-ca.certificate: > -        {{ hawkular_secrets['ca.crt'] }} +      tls.key: > +        {{ hawkular_secrets['hawkular-metrics.key'] }} +      tls.truststore.crt: > +        {{ hawkular_secrets['hawkular-cassandra.crt'] }}    when: name not in metrics_secrets.stdout_lines    changed_when: no @@ -122,6 +84,7 @@        metrics-infra: hawkular-metrics      data:        hawkular-metrics.username: "{{ 'hawkular'|b64encode }}" +      hawkular-metrics.htpasswd: "{{ hawkular_secrets['hawkular-metrics.htpasswd'] }}"        hawkular-metrics.password: >          {{ hawkular_secrets['hawkular-metrics.pwd'] }}    when: name not in metrics_secrets.stdout_lines diff --git a/roles/openshift_metrics/tasks/import_jks_certs.yaml b/roles/openshift_metrics/tasks/import_jks_certs.yaml deleted file mode 100644 index e098145e9..000000000 --- a/roles/openshift_metrics/tasks/import_jks_certs.yaml +++ /dev/null @@ -1,37 +0,0 @@ ---- -- stat: path="{{mktemp.stdout}}/hawkular-metrics.keystore" -  register: metrics_keystore -  check_mode: no - -- stat: path="{{mktemp.stdout}}/hawkular-metrics.truststore" -  register: metrics_truststore -  check_mode: no - -- block: -  - slurp: src={{ mktemp.stdout }}/hawkular-metrics-keystore.pwd -    register: metrics_keystore_password - -  - fetch: -      dest: "{{local_tmp.stdout}}/" -      src: "{{ mktemp.stdout }}/{{item}}" -      flat: yes -    changed_when: False -    with_items: -    - hawkular-metrics.pkcs12 -    - hawkular-metrics.crt -    - ca.crt - -  - local_action: command {{role_path}}/files/import_jks_certs.sh -    environment: -      CERT_DIR: "{{local_tmp.stdout}}" -      METRICS_KEYSTORE_PASSWD: "{{metrics_keystore_password.content}}" -      METRICS_TRUSTSTORE_PASSWD: "{{hawkular_truststore_password.content}}" -    changed_when: False - -  - copy: -      dest: "{{mktemp.stdout}}/" -      src: "{{item}}" -    with_fileglob: "{{local_tmp.stdout}}/*.*store" - -  when: not metrics_keystore.stat.exists or -        not metrics_truststore.stat.exists diff --git a/roles/openshift_metrics/tasks/install_heapster.yaml b/roles/openshift_metrics/tasks/install_heapster.yaml index c490bcdd3..8d27c4930 100644 --- a/roles/openshift_metrics/tasks/install_heapster.yaml +++ b/roles/openshift_metrics/tasks/install_heapster.yaml @@ -20,7 +20,7 @@  - set_fact:      heapster_sa_secrets: "{{ heapster_sa_secrets + [item] }}"    with_items: -    - hawkular-metrics-certificate +    - hawkular-metrics-certs      - hawkular-metrics-account    when: "not {{ openshift_metrics_heapster_standalone | bool }}" diff --git a/roles/openshift_metrics/templates/hawkular_metrics_rc.j2 b/roles/openshift_metrics/templates/hawkular_metrics_rc.j2 index 361378df3..401db4e58 100644 --- a/roles/openshift_metrics/templates/hawkular_metrics_rc.j2 +++ b/roles/openshift_metrics/templates/hawkular_metrics_rc.j2 @@ -40,24 +40,20 @@ spec:          - "-Dhawkular.metrics.cassandra.nodes=hawkular-cassandra"          - "-Dhawkular.metrics.cassandra.use-ssl"          - "-Dhawkular.metrics.openshift.auth-methods=openshift-oauth,htpasswd" -        - "-Dhawkular.metrics.openshift.htpasswd-file=/secrets/hawkular-metrics.htpasswd.file" +        - "-Dhawkular.metrics.openshift.htpasswd-file=/hawkular-account/hawkular-metrics.htpasswd"          - "-Dhawkular.metrics.allowed-cors-access-control-allow-headers=authorization"          - "-Dhawkular.metrics.default-ttl={{openshift_metrics_duration}}"          - "-Dhawkular.metrics.admin-tenant=_hawkular_admin"          - "-Dhawkular-alerts.cassandra-nodes=hawkular-cassandra"          - "-Dhawkular-alerts.cassandra-use-ssl"          - "-Dhawkular.alerts.openshift.auth-methods=openshift-oauth,htpasswd" -        - "-Dhawkular.alerts.openshift.htpasswd-file=/secrets/hawkular-metrics.htpasswd.file" +        - "-Dhawkular.alerts.openshift.htpasswd-file=/hawkular-account/hawkular-metrics.htpasswd"          - "-Dhawkular.alerts.allowed-cors-access-control-allow-headers=authorization"          - "-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true"          - "-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true"          - "-Dcom.datastax.driver.FORCE_NIO=true"          - "-DKUBERNETES_MASTER_URL={{openshift_metrics_master_url}}"          - "-DUSER_WRITE_ACCESS={{openshift_metrics_hawkular_user_write_access}}" -        - "--hmw.keystore=/secrets/hawkular-metrics.keystore" -        - "--hmw.truststore=/secrets/hawkular-metrics.truststore" -        - "--hmw.keystore_password_file=/secrets/hawkular-metrics.keystore.password" -        - "--hmw.truststore_password_file=/secrets/hawkular-metrics.truststore.password"          env:          - name: POD_NAMESPACE            valueFrom: @@ -67,6 +63,8 @@ spec:            value: "{{ openshift_metrics_master_url }}"          - name: JGROUPS_PASSWORD            value: "{{ 17 | oo_random_word }}" +        - name: TRUSTSTORE_AUTHORITIES +          value: "/hawkular-metrics-certs/tls.truststore.crt"          - name: OPENSHIFT_KUBE_PING_NAMESPACE            valueFrom:              fieldRef: @@ -76,10 +74,10 @@ spec:          - name: STARTUP_TIMEOUT            value: "{{ openshift_metrics_startup_timeout }}"          volumeMounts: -        - name: hawkular-metrics-secrets -          mountPath: "/secrets" -        - name: hawkular-metrics-client-secrets -          mountPath: "/client-secrets" +        - name: hawkular-metrics-certs +          mountPath: "/hawkular-metrics-certs" +        - name: hawkular-metrics-account +          mountPath: "/hawkular-account"  {% if ((openshift_metrics_hawkular_limits_cpu is defined and openshift_metrics_hawkular_limits_cpu is not none)     or (openshift_metrics_hawkular_limits_memory is defined and openshift_metrics_hawkular_limits_memory is not none)     or (openshift_metrics_hawkular_requests_cpu is defined and openshift_metrics_hawkular_requests_cpu is not none) @@ -118,9 +116,9 @@ spec:              command:              - "/opt/hawkular/scripts/hawkular-metrics-liveness.py"        volumes: -      - name: hawkular-metrics-secrets +      - name: hawkular-metrics-certs          secret: -          secretName: hawkular-metrics-secrets -      - name: hawkular-metrics-client-secrets +          secretName: hawkular-metrics-certs +      - name: hawkular-metrics-account          secret:            secretName: hawkular-metrics-account diff --git a/roles/openshift_metrics/templates/heapster.j2 b/roles/openshift_metrics/templates/heapster.j2 index 7c837db4d..f01ccfd58 100644 --- a/roles/openshift_metrics/templates/heapster.j2 +++ b/roles/openshift_metrics/templates/heapster.j2 @@ -43,15 +43,15 @@ spec:          - "--wrapper.username_file=/hawkular-account/hawkular-metrics.username"          - "--wrapper.password_file=/hawkular-account/hawkular-metrics.password"          - "--wrapper.endpoint_check=https://hawkular-metrics:443/hawkular/metrics/status" -        - "--sink=hawkular:https://hawkular-metrics:443?tenant=_system&labelToTenant=pod_namespace&labelNodeId={{openshift_metrics_node_id}}&caCert=/hawkular-cert/hawkular-metrics-ca.certificate&user=%username%&pass=%password%&filter=label(container_name:^system.slice.*|^user.slice)" +        - "--sink=hawkular:https://hawkular-metrics:443?tenant=_system&labelToTenant=pod_namespace&labelNodeId={{openshift_metrics_node_id}}&caCert=/hawkular-metrics-certs/tls.crt&user=%username%&pass=%password%&filter=label(container_name:^system.slice.*|^user.slice)"  {% endif %}          env:          - name: STARTUP_TIMEOUT            value: "{{ openshift_metrics_startup_timeout }}" -{% if ((openshift_metrics_heapster_limits_cpu is defined and openshift_metrics_heapster_limits_cpu is not none)  +{% if ((openshift_metrics_heapster_limits_cpu is defined and openshift_metrics_heapster_limits_cpu is not none)     or (openshift_metrics_heapster_limits_memory is defined and openshift_metrics_heapster_limits_memory is not none)     or (openshift_metrics_heapster_requests_cpu is defined and openshift_metrics_heapster_requests_cpu is not none) -   or (openshift_metrics_heapster_requests_memory is defined and openshift_metrics_heapster_requests_memory is not none))  +   or (openshift_metrics_heapster_requests_memory is defined and openshift_metrics_heapster_requests_memory is not none))  %}          resources:  {% if (openshift_metrics_heapster_limits_cpu is not none @@ -65,8 +65,8 @@ spec:              memory: "{{openshift_metrics_heapster_limits_memory}}"  {% endif %}  {% endif %} -{% if (openshift_metrics_heapster_requests_cpu is not none  -   or openshift_metrics_heapster_requests_memory is not none)  +{% if (openshift_metrics_heapster_requests_cpu is not none +   or openshift_metrics_heapster_requests_memory is not none)  %}            requests:  {% if openshift_metrics_heapster_requests_cpu is not none %} @@ -81,8 +81,8 @@ spec:          - name: heapster-secrets            mountPath: "/secrets"  {% if not openshift_metrics_heapster_standalone %} -        - name: hawkular-metrics-certificate -          mountPath: "/hawkular-cert" +        - name: hawkular-metrics-certs +          mountPath: "/hawkular-metrics-certs"          - name: hawkular-metrics-account            mountPath: "/hawkular-account"          readinessProbe: @@ -95,9 +95,9 @@ spec:            secret:              secretName: heapster-secrets  {% if not openshift_metrics_heapster_standalone %} -        - name: hawkular-metrics-certificate +        - name: hawkular-metrics-certs            secret: -            secretName: hawkular-metrics-certificate +            secretName: hawkular-metrics-certs          - name: hawkular-metrics-account            secret:              secretName: hawkular-metrics-account diff --git a/roles/openshift_provisioners/README.md b/roles/openshift_provisioners/README.md new file mode 100644 index 000000000..7449073e6 --- /dev/null +++ b/roles/openshift_provisioners/README.md @@ -0,0 +1,29 @@ +# OpenShift External Dynamic Provisioners + +## Required Vars +* `openshift_provisioners_install_provisioners`: When `True` the openshift_provisioners role will install provisioners that have their "master" var (e.g. `openshift_provisioners_efs`) set `True`. When `False` will uninstall provisioners that have their var set `True`. + +## Optional Vars +* `openshift_provisioners_image_prefix`: The prefix for the provisioner images to use. Defaults to 'docker.io/openshift/origin-'. +* `openshift_provisioners_image_version`: The image version for the provisioner images to use. Defaults to 'latest'. +* `openshift_provisioners_project`: The namespace that provisioners will be installed in. Defaults to 'openshift-infra'. + +## AWS EFS + +### Prerequisites +* An IAM user assigned the AmazonElasticFileSystemReadOnlyAccess policy (or better) +* An EFS file system in your cluster's region +* [Mount targets](http://docs.aws.amazon.com/efs/latest/ug/accessing-fs.html) and [security groups](http://docs.aws.amazon.com/efs/latest/ug/accessing-fs-create-security-groups.html) such that any node (in any zone in the cluster's region) can mount the EFS file system by its [File system DNS name](http://docs.aws.amazon.com/efs/latest/ug/mounting-fs-mount-cmd-dns-name.html) + +### Required Vars +* `openshift_provisioners_efs_fsid`: The [File system ID](http://docs.aws.amazon.com/efs/latest/ug/gs-step-two-create-efs-resources.html) of the EFS file system, e.g. fs-47a2c22e. +* `openshift_provisioners_efs_region`: The Amazon EC2 region of the EFS file system. +* `openshift_provisioners_efs_aws_access_key_id`: The AWS access key of the IAM user, used to check that the EFS file system specified actually exists. +* `openshift_provisioners_efs_aws_secret_access_key`: The AWS secret access key of the IAM user, used to check that the EFS file system specified actually exists. + +### Optional Vars +* `openshift_provisioners_efs`: When `True` the AWS EFS provisioner will be installed or uninstalled according to whether `openshift_provisioners_install_provisioners` is `True` or `False`, respectively. Defaults to `False`. +* `openshift_provisioners_efs_path`: The path of the directory in the EFS file system in which the EFS provisioner will create a directory to back each PV it creates. It must exist and be mountable by the EFS provisioner. Defaults to '/persistentvolumes'. +* `openshift_provisioners_efs_name`: The `provisioner` name that `StorageClasses` specify. Defaults to 'openshift.org/aws-efs'. +* `openshift_provisioners_efs_nodeselector`: A map of labels (e.g. {"node":"infra","region":"west"} to select the nodes where the pod will land. +* `openshift_provisioners_efs_supplementalgroup`: The supplemental group to give the pod in case it is needed for permission to write to the EFS file system. Defaults to '65534'. diff --git a/roles/openshift_provisioners/defaults/main.yaml b/roles/openshift_provisioners/defaults/main.yaml new file mode 100644 index 000000000..a6f040831 --- /dev/null +++ b/roles/openshift_provisioners/defaults/main.yaml @@ -0,0 +1,12 @@ +--- +openshift_provisioners_install_provisioners: True +openshift_provisioners_image_prefix: docker.io/openshift/origin- +openshift_provisioners_image_version: latest + +openshift_provisioners_efs: False +openshift_provisioners_efs_path: /persistentvolumes +openshift_provisioners_efs_name: openshift.org/aws-efs +openshift_provisioners_efs_nodeselector: "" +openshift_provisioners_efs_supplementalgroup: '65534' + +openshift_provisioners_project: openshift-infra diff --git a/roles/openshift_provisioners/meta/main.yaml b/roles/openshift_provisioners/meta/main.yaml new file mode 100644 index 000000000..cb9278eb7 --- /dev/null +++ b/roles/openshift_provisioners/meta/main.yaml @@ -0,0 +1,16 @@ +--- +galaxy_info: +  author: OpenShift Red Hat +  description: OpenShift Provisioners +  company: Red Hat, Inc. +  license: Apache License, Version 2.0 +  min_ansible_version: 2.2 +  platforms: +  - name: EL +    versions: +    - 7 +  categories: +  - cloud +dependencies: +- role: lib_openshift +- role: openshift_facts diff --git a/roles/openshift_provisioners/tasks/generate_clusterrolebindings.yaml b/roles/openshift_provisioners/tasks/generate_clusterrolebindings.yaml new file mode 100644 index 000000000..ac21a5e37 --- /dev/null +++ b/roles/openshift_provisioners/tasks/generate_clusterrolebindings.yaml @@ -0,0 +1,19 @@ +--- +- name: Generate ClusterRoleBindings +  template: src=clusterrolebinding.j2 dest={{mktemp.stdout}}/templates/{{obj_name}}-clusterrolebinding.yaml +  vars: +    acct_name: provisioners-{{item}} +    obj_name: run-provisioners-{{item}} +    labels: +      provisioners-infra: support +    crb_usernames: ["system:serviceaccount:{{openshift_provisioners_project}}:{{acct_name}}"] +    subjects: +      - kind: ServiceAccount +        name: "{{acct_name}}" +        namespace: "{{openshift_provisioners_project}}" +    cr_name: "system:persistent-volume-provisioner" +  with_items: +    # TODO +    - efs +  check_mode: no +  changed_when: no diff --git a/roles/openshift_provisioners/tasks/generate_secrets.yaml b/roles/openshift_provisioners/tasks/generate_secrets.yaml new file mode 100644 index 000000000..e6cbb1bbf --- /dev/null +++ b/roles/openshift_provisioners/tasks/generate_secrets.yaml @@ -0,0 +1,14 @@ +--- +- name: Generate secret for efs +  template: src=secret.j2 dest={{mktemp.stdout}}/templates/{{obj_name}}-secret.yaml +  vars: +    name: efs +    obj_name: "provisioners-efs" +    labels: +      provisioners-infra: support +    secrets: +      - {key: aws-access-key-id, value: "{{openshift_provisioners_efs_aws_access_key_id}}"} +      - {key: aws-secret-access-key, value: "{{openshift_provisioners_efs_aws_secret_access_key}}"} +  check_mode: no +  changed_when: no +  when: openshift_provisioners_efs | bool diff --git a/roles/openshift_provisioners/tasks/generate_serviceaccounts.yaml b/roles/openshift_provisioners/tasks/generate_serviceaccounts.yaml new file mode 100644 index 000000000..4fe0583ee --- /dev/null +++ b/roles/openshift_provisioners/tasks/generate_serviceaccounts.yaml @@ -0,0 +1,12 @@ +--- +- name: Generating serviceaccounts +  template: src=serviceaccount.j2 dest={{mktemp.stdout}}/templates/{{obj_name}}-sa.yaml +  vars: +    obj_name: provisioners-{{item}} +    labels: +      provisioners-infra: support +  with_items: +  # TODO +  - efs +  check_mode: no +  changed_when: no diff --git a/roles/openshift_provisioners/tasks/install_efs.yaml b/roles/openshift_provisioners/tasks/install_efs.yaml new file mode 100644 index 000000000..57279c665 --- /dev/null +++ b/roles/openshift_provisioners/tasks/install_efs.yaml @@ -0,0 +1,70 @@ +--- +- name: Check efs current replica count +  command: > +    {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig get dc provisioners-efs +    -o jsonpath='{.spec.replicas}' -n {{openshift_provisioners_project}} +  register: efs_replica_count +  when: not ansible_check_mode +  ignore_errors: yes +  changed_when: no + +- name: Generate efs PersistentVolumeClaim +  template: src=pvc.j2 dest={{mktemp.stdout}}/templates/{{obj_name}}-pvc.yaml +  vars: +    obj_name: "provisioners-efs" +    size: "1Mi" +    access_modes: +      - "ReadWriteMany" +    pv_selector: +      provisioners-efs: efs +  check_mode: no +  changed_when: no + +- name: Generate efs PersistentVolume +  template: src=pv.j2 dest={{mktemp.stdout}}/templates/{{obj_name}}-pv.yaml +  vars: +    obj_name: "provisioners-efs" +    size: "1Mi" +    access_modes: +      - "ReadWriteMany" +    labels: +      provisioners-efs: efs +    volume_plugin: "nfs" +    volume_source: +      - {key: "server", value: "{{openshift_provisioners_efs_fsid}}.efs.{{openshift_provisioners_efs_region}}.amazonaws.com"} +      - {key: "path", value: "{{openshift_provisioners_efs_path}}"} +    claim_name: "provisioners-efs" +  check_mode: no +  changed_when: no + +- name: Generate efs DeploymentConfig +  template: +    src: efs.j2 +    dest: "{{ mktemp.stdout }}/templates/{{deploy_name}}-dc.yaml" +  vars: +    name: efs +    deploy_name: "provisioners-efs" +    deploy_serviceAccount: "provisioners-efs" +    replica_count: "{{efs_replica_count.stdout | default(0)}}" +    node_selector: "{{openshift_provisioners_efs_nodeselector | default('') }}" +    claim_name: "provisioners-efs" +  check_mode: no +  changed_when: false + +# anyuid in order to run as root & chgrp shares with allocated gids +- name: "Check efs anyuid permissions" +  command: > +    {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig +    get scc/anyuid -o jsonpath='{.users}' +  register: efs_anyuid +  check_mode: no +  changed_when: no + +- name: "Set anyuid permissions for efs" +  command: > +    {{ openshift.common.admin_binary}} --config={{ mktemp.stdout }}/admin.kubeconfig policy +    add-scc-to-user anyuid system:serviceaccount:{{openshift_provisioners_project}}:provisioners-efs +  register: efs_output +  failed_when: "efs_output.rc == 1 and 'exists' not in efs_output.stderr" +  check_mode: no +  when: efs_anyuid.stdout.find("system:serviceaccount:{{openshift_provisioners_project}}:provisioners-efs") == -1 diff --git a/roles/openshift_provisioners/tasks/install_provisioners.yaml b/roles/openshift_provisioners/tasks/install_provisioners.yaml new file mode 100644 index 000000000..324fdcc82 --- /dev/null +++ b/roles/openshift_provisioners/tasks/install_provisioners.yaml @@ -0,0 +1,55 @@ +--- +- name: Check that EFS File System ID is set +  fail: msg='the openshift_provisioners_efs_fsid variable is required' +  when: (openshift_provisioners_efs | bool) and openshift_provisioners_efs_fsid is not defined + +- name: Check that EFS region is set +  fail: msg='the openshift_provisioners_efs_region variable is required' +  when: (openshift_provisioners_efs | bool) and openshift_provisioners_efs_region is not defined + +- name: Check that EFS AWS access key id is set +  fail: msg='the openshift_provisioners_efs_aws_access_key_id variable is required' +  when: (openshift_provisioners_efs | bool) and openshift_provisioners_efs_aws_access_key_id is not defined + +- name: Check that EFS AWS secret access key is set +  fail: msg='the openshift_provisioners_efs_aws_secret_access_key variable is required' +  when: (openshift_provisioners_efs | bool) and openshift_provisioners_efs_aws_secret_access_key is not defined + +- name: Install support +  include: install_support.yaml + +- name: Install EFS +  include: install_efs.yaml +  when: openshift_provisioners_efs | bool + +- find: paths={{ mktemp.stdout }}/templates patterns=*.yaml +  register: object_def_files +  changed_when: no + +- slurp: src={{item}} +  register: object_defs +  with_items: "{{object_def_files.files | map(attribute='path') | list | sort}}" +  changed_when: no + +- name: Create objects +  include: oc_apply.yaml +  vars: +    - kubeconfig: "{{ mktemp.stdout }}/admin.kubeconfig" +    - namespace: "{{ openshift_provisioners_project }}" +    - file_name: "{{ file.source }}" +    - file_content: "{{ file.content | b64decode | from_yaml }}" +  with_items: "{{ object_defs.results }}" +  loop_control: +    loop_var: file +  when: not ansible_check_mode + +- name: Printing out objects to create +  debug: msg={{file.content | b64decode }} +  with_items: "{{ object_defs.results }}" +  loop_control: +    loop_var: file +  when: ansible_check_mode + +- name: Scaling up cluster +  include: start_cluster.yaml +  when: start_cluster | default(true) | bool diff --git a/roles/openshift_provisioners/tasks/install_support.yaml b/roles/openshift_provisioners/tasks/install_support.yaml new file mode 100644 index 000000000..ba472f1c9 --- /dev/null +++ b/roles/openshift_provisioners/tasks/install_support.yaml @@ -0,0 +1,24 @@ +--- +- name: Check for provisioners project already exists +  command: > +    {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig get project {{openshift_provisioners_project}} --no-headers +  register: provisioners_project_result +  ignore_errors: yes +  when: not ansible_check_mode +  changed_when: no + +- name: Create provisioners project +  command: > +    {{ openshift.common.admin_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig new-project {{openshift_provisioners_project}} +  when: not ansible_check_mode and "not found" in provisioners_project_result.stderr + +- name: Create temp directory for all our templates +  file: path={{mktemp.stdout}}/templates state=directory mode=0755 +  changed_when: False +  check_mode: no + +- include: generate_secrets.yaml + +- include: generate_clusterrolebindings.yaml + +- include: generate_serviceaccounts.yaml diff --git a/roles/openshift_provisioners/tasks/main.yaml b/roles/openshift_provisioners/tasks/main.yaml new file mode 100644 index 000000000..a50c78c97 --- /dev/null +++ b/roles/openshift_provisioners/tasks/main.yaml @@ -0,0 +1,27 @@ +--- +- name: Create temp directory for doing work in +  command: mktemp -td openshift-provisioners-ansible-XXXXXX +  register: mktemp +  changed_when: False +  check_mode: no + +- name: Copy the admin client config(s) +  command: > +    cp {{ openshift.common.config_base}}/master/admin.kubeconfig {{ mktemp.stdout }}/admin.kubeconfig +  changed_when: False +  check_mode: no +  tags: provisioners_init + +- include: "{{ role_path }}/tasks/install_provisioners.yaml" +  when: openshift_provisioners_install_provisioners | default(false) | bool + +- include: "{{ role_path }}/tasks/uninstall_provisioners.yaml" +  when: not openshift_provisioners_install_provisioners | default(false) | bool + +- name: Delete temp directory +  file: +    name: "{{ mktemp.stdout }}" +    state: absent +  tags: provisioners_cleanup +  changed_when: False +  check_mode: no diff --git a/roles/openshift_provisioners/tasks/oc_apply.yaml b/roles/openshift_provisioners/tasks/oc_apply.yaml new file mode 100644 index 000000000..49d03f203 --- /dev/null +++ b/roles/openshift_provisioners/tasks/oc_apply.yaml @@ -0,0 +1,51 @@ +--- +- name: Checking generation of {{file_content.kind}} {{file_content.metadata.name}} +  command: > +    {{ openshift.common.client_binary }} --config={{ kubeconfig }} +    get {{file_content.kind}} {{file_content.metadata.name}} +    -o jsonpath='{.metadata.resourceVersion}' +    -n {{namespace}} +  register: generation_init +  failed_when: "'not found' not in generation_init.stderr and generation_init.stdout == ''" +  changed_when: no + +- name: Applying {{file_name}} +  command: > +    {{ openshift.common.client_binary }} --config={{ kubeconfig }} +    apply -f {{ file_name }} +    -n {{ namespace }} +  register: generation_apply +  failed_when: "'error' in generation_apply.stderr" +  changed_when: no + +- name: Determine change status of {{file_content.kind}} {{file_content.metadata.name}} +  command: > +    {{ openshift.common.client_binary }} --config={{ kubeconfig }} +    get {{file_content.kind}} {{file_content.metadata.name}} +    -o jsonpath='{.metadata.resourceVersion}' +    -n {{namespace}} +  register: generation_changed +  failed_when: "'not found' not in generation_changed.stderr and generation_changed.stdout == ''" +  changed_when: generation_changed.stdout | default (0) | int  > generation_init.stdout | default(0) | int +  when: +    - "'field is immutable' not in generation_apply.stderr" + +- name: Removing previous {{file_name}} +  command: > +    {{ openshift.common.client_binary }} --config={{ kubeconfig }} +    delete -f {{ file_name }} +    -n {{ namespace }} +  register: generation_delete +  failed_when: "'error' in generation_delete.stderr" +  changed_when: generation_delete.rc == 0 +  when: generation_apply.rc != 0 + +- name: Recreating {{file_name}} +  command: > +    {{ openshift.common.client_binary }} --config={{ kubeconfig }} +    apply -f {{ file_name }} +    -n {{ namespace }} +  register: generation_apply +  failed_when: "'error' in generation_apply.stderr" +  changed_when: generation_apply.rc == 0 +  when: generation_apply.rc != 0 diff --git a/roles/openshift_provisioners/tasks/start_cluster.yaml b/roles/openshift_provisioners/tasks/start_cluster.yaml new file mode 100644 index 000000000..ee7f545a9 --- /dev/null +++ b/roles/openshift_provisioners/tasks/start_cluster.yaml @@ -0,0 +1,20 @@ +--- +- name: Retrieve efs +  oc_obj: +    state: list +    kind: dc +    selector: "provisioners-infra=efs" +    namespace: "{{openshift_provisioners_project}}" +  register: efs_dc +  when: openshift_provisioners_efs | bool + +- name: start efs +  oc_scale: +    kind: dc +    name: "{{ object }}" +    namespace: "{{openshift_provisioners_project}}" +    replicas: 1 +  with_items: "{{ efs_dc.results.results[0]['items'] | map(attribute='metadata.name') | list }}" +  loop_control: +    loop_var: object +  when: openshift_provisioners_efs | bool diff --git a/roles/openshift_provisioners/tasks/stop_cluster.yaml b/roles/openshift_provisioners/tasks/stop_cluster.yaml new file mode 100644 index 000000000..30b6b12c8 --- /dev/null +++ b/roles/openshift_provisioners/tasks/stop_cluster.yaml @@ -0,0 +1,20 @@ +--- +- name: Retrieve efs +  oc_obj: +    state: list +    kind: dc +    selector: "provisioners-infra=efs" +    namespace: "{{openshift_provisioners_project}}" +  register: efs_dc +  when: openshift_provisioners_efs | bool + +- name: stop efs +  oc_scale: +    kind: dc +    name: "{{ object }}" +    namespace: "{{openshift_provisioners_project}}" +    replicas: 0 +  with_items: "{{ efs_dc.results.results[0]['items'] | map(attribute='metadata.name') | list }}" +  loop_control: +    loop_var: object +  when: openshift_provisioners_efs | bool diff --git a/roles/openshift_provisioners/tasks/uninstall_provisioners.yaml b/roles/openshift_provisioners/tasks/uninstall_provisioners.yaml new file mode 100644 index 000000000..0be4bc7d2 --- /dev/null +++ b/roles/openshift_provisioners/tasks/uninstall_provisioners.yaml @@ -0,0 +1,43 @@ +--- +- name: stop provisioners +  include: stop_cluster.yaml + +# delete the deployment objects that we had created +- name: delete provisioner api objects +  command: > +    {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig +    delete {{ item }} --selector provisioners-infra -n {{ openshift_provisioners_project }} --ignore-not-found=true +  with_items: +    - dc +  register: delete_result +  changed_when: delete_result.stdout.find("deleted") != -1 and delete_result.rc == 0 + +# delete our old secrets +- name: delete provisioner secrets +  command: > +    {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig +    delete secret {{ item }} -n {{ openshift_provisioners_project }} --ignore-not-found=true +  with_items: +    - provisioners-efs +  ignore_errors: yes +  register: delete_result +  changed_when: delete_result.stdout.find("deleted") != -1 and delete_result.rc == 0 + +# delete cluster role bindings +- name: delete cluster role bindings +  command: > +    {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig +    delete clusterrolebindings {{ item }} -n {{ openshift_provisioners_project }} --ignore-not-found=true +  with_items: +    - run-provisioners-efs +  register: delete_result +  changed_when: delete_result.stdout.find("deleted") != -1 and delete_result.rc == 0 + +# delete our service accounts +- name: delete service accounts +  oc_serviceaccount: +    name: "{{ item }}" +    namespace: "{{ openshift_provisioners_project }}" +    state: absent +  with_items: +    - provisioners-efs diff --git a/roles/openshift_provisioners/templates/clusterrolebinding.j2 b/roles/openshift_provisioners/templates/clusterrolebinding.j2 new file mode 100644 index 000000000..994afa32d --- /dev/null +++ b/roles/openshift_provisioners/templates/clusterrolebinding.j2 @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: ClusterRoleBinding +metadata: +  name: {{obj_name}} +{% if labels is defined%} +  labels: +{% for key, value in labels.iteritems() %} +    {{key}}: {{value}} +{% endfor %} +{% endif %} +{% if crb_usernames is defined %} +userNames: +{% for name in crb_usernames %} +  - {{ name }} +{% endfor %} +{% endif %} +{% if crb_groupnames is defined %} +groupNames: +{% for name in crb_groupnames %} +  - {{ name }} +{% endfor %} +{% endif %} +subjects: +{% for sub in subjects %} +  - kind: {{ sub.kind }} +    name: {{ sub.name }} +    namespace: {{sub.namespace}} +{% endfor %} +roleRef: +  name: {{cr_name}} diff --git a/roles/openshift_provisioners/templates/efs.j2 b/roles/openshift_provisioners/templates/efs.j2 new file mode 100644 index 000000000..81b9ccca5 --- /dev/null +++ b/roles/openshift_provisioners/templates/efs.j2 @@ -0,0 +1,58 @@ +kind: DeploymentConfig +apiVersion: v1 +metadata: +  name: "{{deploy_name}}" +  labels: +    provisioners-infra: "{{name}}" +    name: "{{name}}" +spec: +  replicas: {{replica_count}} +  selector: +    provisioners-infra: "{{name}}" +    name: "{{name}}" +  strategy: +    type: Recreate  +  template: +    metadata: +      name: "{{deploy_name}}" +      labels: +        provisioners-infra: "{{name}}" +        name: "{{name}}" +    spec: +      serviceAccountName: "{{deploy_serviceAccount}}" +{% if node_selector is iterable and node_selector | length > 0 %} +      nodeSelector: +{% for key, value in node_selector.iteritems() %} +        {{key}}: "{{value}}" +{% endfor %} +{% endif %} +      containers: +        - name: efs-provisioner +          image: {{openshift_provisioners_image_prefix}}efs-provisioner:{{openshift_provisioners_image_version}} +          env: +            - name: AWS_ACCESS_KEY_ID +              valueFrom: +                secretKeyRef: +                  name: provisioners-efs +                  key: aws-access-key-id +            - name: AWS_SECRET_ACCESS_KEY +              valueFrom: +                secretKeyRef: +                  name: provisioners-efs +                  key: aws-secret-access-key +            - name: FILE_SYSTEM_ID +              value: "{{openshift_provisioners_efs_fsid}}" +            - name: AWS_REGION +              value: "{{openshift_provisioners_efs_region}}" +            - name: PROVISIONER_NAME +              value: "{{openshift_provisioners_efs_name}}" +          volumeMounts: +            - name: pv-volume +              mountPath: /persistentvolumes +      securityContext: +        supplementalGroups: +          - {{openshift_provisioners_efs_supplementalgroup}} +      volumes: +        - name: pv-volume +          persistentVolumeClaim: +            claimName: "{{claim_name}}" diff --git a/roles/openshift_provisioners/templates/pv.j2 b/roles/openshift_provisioners/templates/pv.j2 new file mode 100644 index 000000000..f4128f9f0 --- /dev/null +++ b/roles/openshift_provisioners/templates/pv.j2 @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: +  name: {{obj_name}} +{% if annotations is defined %} +  annotations: +{% for key,value in annotations.iteritems() %} +    {{key}}: {{value}} +{% endfor %} +{% endif %} +{% if labels is defined%} +  labels: +{% for key, value in labels.iteritems() %} +    {{key}}: {{value}} +{% endfor %} +{% endif %} +spec: +  capacity: +    storage: {{size}} +  accessModes: +{% for mode in access_modes %} +    - {{mode}} +{% endfor %} +  {{volume_plugin}}: +{% for s in volume_source %} +    {{s.key}}: {{s.value}} +{% endfor %} +{% if claim_name is defined%} +  claimRef: +    name: {{claim_name}} +    namespace: {{openshift_provisioners_project}} +{% endif %} diff --git a/roles/openshift_provisioners/templates/pvc.j2 b/roles/openshift_provisioners/templates/pvc.j2 new file mode 100644 index 000000000..83d503056 --- /dev/null +++ b/roles/openshift_provisioners/templates/pvc.j2 @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: +  name: {{obj_name}} +{% if annotations is defined %} +  annotations: +{% for key,value in annotations.iteritems() %} +    {{key}}: {{value}} +{% endfor %} +{% endif %} +spec: +{% if pv_selector is defined and pv_selector is mapping %} +  selector: +    matchLabels: +{% for key,value in pv_selector.iteritems() %} +      {{key}}: {{value}} +{% endfor %} +{% endif %} +  accessModes: +{% for mode in access_modes %} +    - {{mode}} +{% endfor %} +  resources: +    requests: +      storage: {{size}} + diff --git a/roles/openshift_provisioners/templates/secret.j2 b/roles/openshift_provisioners/templates/secret.j2 new file mode 100644 index 000000000..78824095b --- /dev/null +++ b/roles/openshift_provisioners/templates/secret.j2 @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: +  name: {{obj_name}} +{% if labels is defined%} +  labels: +{% for key, value in labels.iteritems() %} +    {{key}}: {{value}} +{% endfor %} +{% endif %} +type: Opaque +data: +{% for s in secrets %} +  "{{s.key}}" : "{{s.value | b64encode}}" +{% endfor %} diff --git a/roles/openshift_provisioners/templates/serviceaccount.j2 b/roles/openshift_provisioners/templates/serviceaccount.j2 new file mode 100644 index 000000000..b22acc594 --- /dev/null +++ b/roles/openshift_provisioners/templates/serviceaccount.j2 @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: +  name: {{obj_name}} +{% if labels is defined%} +  labels: +{% for key, value in labels.iteritems() %} +    {{key}}: {{value}} +{% endfor %} +{% endif %} +{% if secrets is defined %} +secrets: +{% for name in secrets %} +- name: {{ name }} +{% endfor %} +{% endif %} diff --git a/roles/openshift_repos/README.md b/roles/openshift_repos/README.md index 95b155b29..abd1997dd 100644 --- a/roles/openshift_repos/README.md +++ b/roles/openshift_repos/README.md @@ -12,10 +12,10 @@ rhel-7-server-extra-rpms, and rhel-7-server-ose-3.0-rpms repos.  Role Variables  -------------- -| Name                          | Default value |                                              | -|-------------------------------|---------------|----------------------------------------------| -| openshift_deployment_type     | None          | Possible values enterprise, origin, online   | -| openshift_additional_repos    | {}            | TODO                                         | +| Name                          | Default value |                                    | +|-------------------------------|---------------|------------------------------------| +| openshift_deployment_type     | None          | Possible values enterprise, origin | +| openshift_additional_repos    | {}            | TODO                               |  Dependencies  ------------ diff --git a/roles/openshift_sanitize_inventory/tasks/main.yml b/roles/openshift_sanitize_inventory/tasks/main.yml index b944c8991..f15dc16d1 100644 --- a/roles/openshift_sanitize_inventory/tasks/main.yml +++ b/roles/openshift_sanitize_inventory/tasks/main.yml @@ -1,4 +1,17 @@  --- +- name: Abort when conflicting deployment type variables are set +  when: +    - deployment_type is defined +    - openshift_deployment_type is defined +    - openshift_deployment_type != deployment_type +  fail: +    msg: |- +      openshift_deployment_type is set to "{{ openshift_deployment_type }}". +      deployment_type is set to "{{ deployment_type }}". +      To avoid unexpected results, this conflict is not allowed. +      deployment_type is deprecated in favor of openshift_deployment_type. +      Please specify only openshift_deployment_type, or make both the same. +  - name: Standardize on latest variable names    set_fact:      # goal is to deprecate deployment_type in favor of openshift_deployment_type.  | 
