github.com/abayer/test-infra@v0.0.5/mungegithub/mungers/mungerutil/util.go (about)

     1  /*
     2  Copyright 2016 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 mungerutil
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"net/http"
    23  	"strings"
    24  	"time"
    25  
    26  	"k8s.io/apimachinery/pkg/util/sets"
    27  
    28  	"github.com/google/go-github/github"
    29  )
    30  
    31  // UserSet is a set a of users
    32  type UserSet sets.String
    33  
    34  // GetUsers returns a UserSet
    35  func GetUsers(users ...*github.User) UserSet {
    36  	allUsers := sets.String{}
    37  
    38  	for _, user := range users {
    39  		if !IsValidUser(user) {
    40  			continue
    41  		}
    42  		allUsers.Insert(*user.Login)
    43  	}
    44  
    45  	return UserSet(allUsers)
    46  }
    47  
    48  // Has tells you if the users can be found in the set
    49  func (u UserSet) Has(user ...*github.User) bool {
    50  	return len(u.intersection(GetUsers(user...))) != 0
    51  }
    52  
    53  // Mention adds @ to user in the list who don't have it yet
    54  func (u UserSet) Mention() UserSet {
    55  	mentionedUsers := sets.NewString()
    56  
    57  	for _, user := range u.List() {
    58  		if !strings.HasPrefix(user, "@") {
    59  			mentionedUsers.Insert("@" + user)
    60  		} else {
    61  			mentionedUsers.Insert(user)
    62  		}
    63  	}
    64  
    65  	return UserSet(mentionedUsers)
    66  }
    67  
    68  // List makes a list from the set
    69  func (u UserSet) List() []string {
    70  	return sets.String(u).List()
    71  }
    72  
    73  // Join joins each users into a single string
    74  func (u UserSet) Join() string {
    75  	return strings.Join(u.List(), " ")
    76  }
    77  
    78  func (u UserSet) union(o UserSet) UserSet {
    79  	return UserSet(sets.String(u).Union(sets.String(o)))
    80  }
    81  
    82  func (u UserSet) intersection(o UserSet) UserSet {
    83  	return UserSet(sets.String(u).Intersection(sets.String(o)))
    84  }
    85  
    86  // IssueUsers tracks Users involved in a github Issue
    87  type IssueUsers struct {
    88  	Assignees UserSet
    89  	Author    UserSet // This will usually be one or zero
    90  }
    91  
    92  // GetIssueUsers creates a new IssueUsers object from an issue's fields
    93  func GetIssueUsers(issue *github.Issue) *IssueUsers {
    94  	return &IssueUsers{
    95  		Assignees: GetUsers(issue.Assignees...).union(GetUsers(issue.Assignee)),
    96  		Author:    GetUsers(issue.User),
    97  	}
    98  }
    99  
   100  // AllUsers return a list of unique users (both assignees and author)
   101  func (u *IssueUsers) AllUsers() UserSet {
   102  	return u.Assignees.union(u.Author)
   103  }
   104  
   105  // IsValidUser returns true only if given user has valid github username.
   106  func IsValidUser(u *github.User) bool {
   107  	return u != nil && u.Login != nil
   108  }
   109  
   110  // ReadHTTP fetches file contents from a URL with retries.
   111  func ReadHTTP(url string) ([]byte, error) {
   112  	var err error
   113  	retryDelay := time.Duration(2) * time.Second
   114  	for retryCount := 0; retryCount < 5; retryCount++ {
   115  		if retryCount > 0 {
   116  			time.Sleep(retryDelay)
   117  			retryDelay *= time.Duration(2)
   118  		}
   119  
   120  		resp, err := http.Get(url)
   121  		if resp != nil && resp.StatusCode >= 500 {
   122  			// Retry on this type of error.
   123  			continue
   124  		}
   125  		if err != nil {
   126  			return nil, err
   127  		}
   128  		defer resp.Body.Close()
   129  
   130  		body, err := ioutil.ReadAll(resp.Body)
   131  		if err != nil {
   132  			continue
   133  		}
   134  		return body, nil
   135  	}
   136  	return nil, fmt.Errorf("ran out of retries reading from '%s'. Last error was %v", url, err)
   137  }