github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/mungegithub/mungers/check-labels.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mungers
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  
    23  	"k8s.io/kubernetes/pkg/util/sets"
    24  	"k8s.io/kubernetes/pkg/util/yaml"
    25  	"k8s.io/test-infra/mungegithub/features"
    26  	githubhelper "k8s.io/test-infra/mungegithub/github"
    27  	"k8s.io/test-infra/mungegithub/mungers/mungerutil"
    28  	"k8s.io/test-infra/mungegithub/options"
    29  
    30  	"bytes"
    31  	"io/ioutil"
    32  
    33  	"github.com/golang/glog"
    34  	"github.com/google/go-github/github"
    35  )
    36  
    37  type labelAccessor interface {
    38  	AddLabel(label *github.Label) error
    39  	GetLabels() ([]*github.Label, error)
    40  }
    41  
    42  // CheckLabelsMunger will check that the labels specified in the labels yaml file
    43  // are created.
    44  type CheckLabelsMunger struct {
    45  	labelFilePath string
    46  	prevHash      string
    47  	labelAccessor labelAccessor
    48  	features      *features.Features
    49  	readFunc      func() ([]byte, error)
    50  }
    51  
    52  func init() {
    53  	RegisterMungerOrDie(&CheckLabelsMunger{})
    54  }
    55  
    56  // Name is the name usable in --pr-mungers
    57  func (c *CheckLabelsMunger) Name() string { return "check-labels" }
    58  
    59  // RequiredFeatures is a slice of 'features' that must be provided.
    60  func (c *CheckLabelsMunger) RequiredFeatures() []string { return []string{features.RepoFeatureName} }
    61  
    62  // Initialize will initialize the munger.
    63  func (c *CheckLabelsMunger) Initialize(config *githubhelper.Config, features *features.Features) error {
    64  	c.labelAccessor = config
    65  	c.features = features
    66  	c.readFunc = func() ([]byte, error) {
    67  		return ioutil.ReadFile(c.labelFilePath)
    68  	}
    69  
    70  	return c.validateFilePath()
    71  }
    72  
    73  func (c *CheckLabelsMunger) validateFilePath() error {
    74  	if len(c.labelFilePath) == 0 {
    75  		return fmt.Errorf("no 'label-file' option specified, cannot check labels")
    76  	}
    77  	if _, err := os.Stat(c.labelFilePath); os.IsNotExist(err) {
    78  		return fmt.Errorf("failed to stat the check label config: %v", err)
    79  	}
    80  	return nil
    81  }
    82  
    83  // EachLoop is called at the start of every munge loop
    84  func (c *CheckLabelsMunger) EachLoop() error {
    85  	fileContents, err := c.readFunc()
    86  	if err != nil {
    87  		glog.Errorf("Failed to read the check label config: %v", err)
    88  		return err
    89  	}
    90  	hash := mungerutil.GetHash(fileContents)
    91  	if c.prevHash != hash {
    92  		// Get all labels from file.
    93  		fileLabels := map[string][]*github.Label{}
    94  		if err := yaml.NewYAMLToJSONDecoder(bytes.NewReader(fileContents)).Decode(&fileLabels); err != nil {
    95  			return fmt.Errorf("Failed to decode the check label config: %v", err)
    96  		}
    97  
    98  		// Get all labels from repository.
    99  		repoLabels, err := c.labelAccessor.GetLabels()
   100  		if err != nil {
   101  			return err
   102  		}
   103  		c.addMissingLabels(repoLabels, fileLabels["labels"])
   104  		c.prevHash = hash
   105  	}
   106  	return nil
   107  }
   108  
   109  // addMissingLabels will not remove any labels. It will add those which are present in the yaml file and not in
   110  // the repository.
   111  func (c *CheckLabelsMunger) addMissingLabels(repoLabels, fileLabels []*github.Label) {
   112  	repoLabelSet := sets.NewString()
   113  	for _, repoLabel := range repoLabels {
   114  		repoLabelSet.Insert(*repoLabel.Name)
   115  	}
   116  
   117  	// Compare against labels in local file.
   118  	for _, label := range fileLabels {
   119  		if !repoLabelSet.Has(*label.Name) {
   120  			err := c.labelAccessor.AddLabel(label)
   121  			if err != nil {
   122  				glog.Errorf("Error %s in adding label %s", err, *label.Name)
   123  			}
   124  		}
   125  	}
   126  }
   127  
   128  // RegisterOptions registers options for this munger; returns any that require a restart when changed.
   129  func (c *CheckLabelsMunger) RegisterOptions(opts *options.Options) sets.String {
   130  	opts.RegisterString(&c.labelFilePath, "label-file", "", "Path from repository root to file containing list of labels.")
   131  	opts.RegisterUpdateCallback(func(changed sets.String) error {
   132  		if changed.Has("label-file") {
   133  			return c.validateFilePath()
   134  		}
   135  		return nil
   136  	})
   137  	return nil
   138  }
   139  
   140  // Munge is unused by this munger.
   141  func (c *CheckLabelsMunger) Munge(obj *githubhelper.MungeObject) {}