Пример #1
0
def route_monitoring(yml: object):
    """
    A route should always be monitored by ormon.

    annotations:
      thobits.com/ormon-valid-statuscodes: 200,300
      thobits.com/ormon-body-regex: Thomann

    note: ormon-valid-statuscodes has to be a string.
    """
    matches = json_path('metadata.annotations."thobits.com/ormon-skip"').find(
        yml)
    if (matches
            and matches[0].value in ['1', 't', 'T', 'TRUE', 'true' or 'True']):
        click.secho(
            f'* resource with disabled monitoring found: {object_ident(yml)}',
            fg='yellow')
        return

    codes = json_path('metadata.annotations."thobits.com/"').find(yml)
    if codes:
        codes = codes.pop().value
        if not all(code.isdigit() for code in codes.split(',')):
            raise LintError(f'invalid statuscodes for {object_ident(yml)}')
        return

    body_regexes = json_path(
        'metadata.annotations."thobits.com/ormon-body-regex"').find(yml)
    if body_regexes:
        body_regex = body_regexes.pop()
        return

    raise LintError(f'no monitoring specified for {object_ident(yml)}')
Пример #2
0
    def named_velero_for(yml: object):
        """
        Validates that a backup or a backup-exclude is defined for each volume.

        annotations:
          backup.velero.io/backup-volumes: data,backup
          backup.velero.io/backup-volumes-excludes: cache

        note: all defined volumes must specify a backup
        """
        ident = object_ident(yml)
        backup_matches = json_path(
            'spec.template.metadata.annotations.'
            '"backup.velero.io/backup-volumes"').find(yml)
        skip_matches = json_path(
            'spec.template.metadata.annotations.'
            '"backup.velero.io/backup-volumes-excludes"').find(yml)
        if not backup_matches:
            raise LintError(f"unable to find velero annotation on {ident}")
        backupped_volumes = backup_matches[0].value.split(',')
        skipped_volumes = []
        if skip_matches:
            skipped_volumes = skip_matches[0].value.split(',')
        if name in skipped_volumes:
            click.secho(f"* backup for volume {name} skipped in {ident}",
                        fg='yellow')
        elif name in backupped_volumes:
            click.secho(f"* backup for volume {name} found in {ident}",
                        fg='green')
        else:
            raise LintError(f"no backup or skip for {name} found in {ident}")
Пример #3
0
def podhandler_pod_disruption_budget(yml: object):
    """require a podhandler for every deployment/statefulset."""
    matches = json_path('spec.template.metadata.labels').find(yml)
    must_validators = []
    for match in matches:
        must_validators.append(pdb_for(object_ident(yml), match.value))
    return ([], must_validators)
Пример #4
0
    def named_pdb_for(yml: object):
        """
        Validates that a matching PodDisruptionBudget for the deployments
        labels exists.

        # example:
        apiVersion: policy/v1beta1
        kind: PodDisruptionBudget
        metadata:
          name: myservice-pdb
          labels:
            app: myservice
            {{- include "helm.labels" . | nindent 4 }}
        spec:
          maxUnavailable: 1
          selector:
            matchLabels:
              app: myservice

        Replace all myservice with service name / other labels.
        """
        ident = object_ident(yml)
        matches = json_path('spec.selector.matchLabels').find(yml)
        if not matches:
            raise LintError(f"* no label matching {name} for {ident}")

        got_labels = matches[0].value
        for key, value in got_labels.items():
            if key not in labels.keys() or labels[key] != value:
                message = (
                    f"pdb {ident} is missing label combination for {name}"
                    f"{key}={value}")
                raise LintError(message)

        click.secho(f"* found pdb {ident} for {name}", fg='green')
Пример #5
0
def backup_stateful(yml: object):
    """Enforce backup annotations for StatefulSet volumeClaimTemplates."""
    matches = json_path('spec.volumeClaimTemplates.[*]').find(yml)
    must_validators = []
    for match in matches:
        name = match.value.get('metadata', {}).get('name')
        must_validators.append(velero_for(name))
    return ([], must_validators)
Пример #6
0
def podhandler_oauth(yml: object):
    """require a route with reencrypt policy if oauth was found enabled."""
    matches = json_path('spec.template.spec.containers.[*]').find(yml)
    gatekeepers = [m for m in matches
                   if 'gatekeeper' in m.value.get('image', '')]
    must_validators = []
    if gatekeepers:
        must_validators.append(
            route_for('gatekeeper', {'spec.tls.termination': 'Reencrypt'})
        )
    return ([], must_validators)
Пример #7
0
def podhandler_git_sha(yml: object):
    """
    This resource requires a git-sha annotation to prevent issues on rolling
    updates with old configmap and secret versions. This annotation must be
    set on "spec.template.metadata.annotations".

    annotations:
      thobits.com/git-sha: 000000
    """
    ident = object_ident(yml)
    matches_bad = json_path(
        'metadata.annotations."thobits.com/git-sha"'
    ).find(yml)
    matches_good = json_path(
        'spec.template.metadata.annotations."thobits.com/git-sha"'
    ).find(yml)
    if matches_bad:
        raise LintError(f'move git-sha annotation to '
                        f'spec.template.metadata.annotations for {ident}')
    if not matches_good:
        raise LintError(f'git-sha missing on {ident}')
Пример #8
0
 def named_route_for(yml: object):
     """
     require the existance of a route with matching parameters
     """
     ident = object_ident(yml)
     for jp, value in json_path_to_value.items():
         matches = json_path(jp).find(yml)
         if not all(m.value == value for m in matches):
             raise LintError(f"{jp}={value} not found")
         click.secho(
             f'* possible matching {ident} for "{name}" '
             f'found({jp}={value})',
             fg='green')
Пример #9
0
def route_warn_public(yml: object):
    """Warn for every public route."""
    matches = json_path(
        'metadata.annotations."acme.openshift.io/exposer"').find(yml)
    if matches:
        click.secho(f'* public route found: {object_ident(yml)}', fg='yellow')