github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/scenarios/kubernetes_janitor.py (about)

     1  #!/usr/bin/env python
     2  
     3  # Copyright 2017 The Kubernetes Authors.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #     http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  # Need to figure out why this only fails on travis
    18  # pylint: disable=bad-continuation
    19  
    20  """Dig through jobs/FOO.env, and execute a janitor pass for each of the project"""
    21  
    22  import argparse
    23  import json
    24  import os
    25  import re
    26  import subprocess
    27  import sys
    28  
    29  ORIG_CWD = os.getcwd()  # Checkout changes cwd
    30  
    31  def test_infra(*paths):
    32      """Return path relative to root of test-infra repo."""
    33      return os.path.join(ORIG_CWD, os.path.dirname(__file__), '..', *paths)
    34  
    35  
    36  def check(*cmd):
    37      """Log and run the command, raising on errors."""
    38      print >>sys.stderr, 'Run:', cmd
    39      subprocess.check_call(cmd)
    40  
    41  
    42  def parse_project(path):
    43      """Parse target env file and return GCP project name."""
    44      with open(path, 'r') as fp:
    45          env = fp.read()
    46      match = re.search(r'PROJECT=([^\n"]+)', env)
    47      if match:
    48          project = match.group(1)
    49          return project
    50      return None
    51  
    52  
    53  def clean_project(project, hours=24, dryrun=False):
    54      """Execute janitor for target GCP project """
    55      # Multiple jobs can share the same project, woooo
    56      if project in CHECKED:
    57          return
    58      CHECKED.add(project)
    59  
    60      cmd = ['python', test_infra('boskos/janitor/janitor.py'), '--project=%s' % project]
    61      cmd.append('--hour=%d' % hours)
    62      if dryrun:
    63          cmd.append('--dryrun')
    64  
    65      try:
    66          check(*cmd)
    67      except subprocess.CalledProcessError:
    68          FAILED.append(project)
    69  
    70  
    71  BLACKLIST = [
    72      '-soak', # We need to keep deployed resources for test uses
    73      'kubernetes-scale', # Let it's up/down job handle the resources
    74  ]
    75  
    76  PR_PROJECTS = {
    77      # k8s-jkns-pr-bldr-e2e-gce-fdrtn
    78      # k8s-jkns-pr-cnry-e2e-gce-fdrtn
    79      # cleans up resources older than 3h
    80      # which is more than enough for presubmit jobs to finish.
    81      'k8s-jkns-pr-gce': 3,
    82      'k8s-jkns-pr-gce-bazel': 3,
    83      'k8s-jkns-pr-gce-etcd3': 3,
    84      'k8s-jkns-pr-gci-gce': 3,
    85      'k8s-jkns-pr-gci-gke': 3,
    86      'k8s-jkns-pr-gci-kubemark': 3,
    87      'k8s-jkns-pr-gke': 3,
    88      'k8s-jkns-pr-kubeadm': 3,
    89      'k8s-jkns-pr-kubemark': 3,
    90      'k8s-jkns-pr-node-e2e': 3,
    91      'k8s-jkns-pr-gce-gpus': 3,
    92      'k8s-gke-gpu-pr': 3,
    93  }
    94  
    95  def check_pr_jobs():
    96      """Handle PR jobs"""
    97      for project, expire in PR_PROJECTS.iteritems():
    98          clean_project(project, hours=expire)
    99  
   100  
   101  def check_ci_jobs():
   102      """Handle CI jobs"""
   103      with open(test_infra('jobs/config.json')) as fp:
   104          config = json.load(fp)
   105  
   106      match_re = re.compile(r'--gcp-project=(.+)')
   107      for value in config.values():
   108          for arg in value.get('args', []):
   109              mat = match_re.match(arg)
   110              if not mat:
   111                  continue
   112              project = mat.group(1)
   113              if any(b in project for b in BLACKLIST):
   114                  print >>sys.stderr, 'Project %r is blacklisted in ci-janitor' % project
   115                  continue
   116              if project in PR_PROJECTS:
   117                  continue # CI janitor skips all PR jobs
   118              clean_project(project)
   119  
   120      # Hard code node-ci project here
   121      clean_project('k8s-jkns-ci-node-e2e')
   122      # gke internal project
   123      clean_project('gke-e2e-createdelete')
   124  
   125  
   126  def main(mode):
   127      """Run janitor for each project."""
   128      if mode == 'pr':
   129          check_pr_jobs()
   130      else:
   131          check_ci_jobs()
   132  
   133      # Summary
   134      print 'Janitor checked %d project, %d failed to clean up.' % (len(CHECKED), len(FAILED))
   135      if FAILED:
   136          print >>sys.stderr, 'Failed projects: %r' % FAILED
   137          exit(1)
   138  
   139  
   140  if __name__ == '__main__':
   141      # keep some metric
   142      CHECKED = set()
   143      FAILED = []
   144      PARSER = argparse.ArgumentParser()
   145      PARSER.add_argument(
   146          '--mode', default='ci', choices=['ci', 'pr'],
   147          help='Which type of projects to clear')
   148      ARGS = PARSER.parse_args()
   149      main(ARGS.mode)