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

     1  /*
     2  Copyright 2017 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 main
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"io"
    23  	"io/ioutil"
    24  	"log"
    25  	"net/http"
    26  	"os"
    27  	"os/exec"
    28  	"strings"
    29  	"time"
    30  )
    31  
    32  var httpTransport *http.Transport
    33  
    34  func init() {
    35  	httpTransport = new(http.Transport)
    36  	httpTransport.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
    37  }
    38  
    39  // Essentially curl url | writer
    40  func httpRead(url string, writer io.Writer) error {
    41  	log.Printf("curl %s", url)
    42  	c := &http.Client{Transport: httpTransport}
    43  	r, err := c.Get(url)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	defer r.Body.Close()
    48  	if r.StatusCode >= 400 {
    49  		return fmt.Errorf("%v returned %d", url, r.StatusCode)
    50  	}
    51  	_, err = io.Copy(writer, r.Body)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	return nil
    56  }
    57  
    58  type instanceGroup struct {
    59  	Name              string `json:"name"`
    60  	CreationTimestamp string `json:"creationTimestamp"`
    61  }
    62  
    63  // getLatestClusterUpTime returns latest created instanceGroup timestamp from gcloud parsing results
    64  func getLatestClusterUpTime(gcloudJSON string) (time.Time, error) {
    65  	igs := []instanceGroup{}
    66  	if err := json.Unmarshal([]byte(gcloudJSON), &igs); err != nil {
    67  		return time.Time{}, fmt.Errorf("error when unmarshal json: %v", err)
    68  	}
    69  
    70  	latest := time.Time{}
    71  
    72  	for _, ig := range igs {
    73  		created, err := time.Parse(time.RFC3339, ig.CreationTimestamp)
    74  		if err != nil {
    75  			return time.Time{}, fmt.Errorf("error when parse time from %s: %v", ig.CreationTimestamp, err)
    76  		}
    77  
    78  		if created.After(latest) {
    79  			latest = created
    80  		}
    81  	}
    82  
    83  	// this returns time.Time{} if no ig exists, which will always force a new cluster
    84  	return latest, nil
    85  }
    86  
    87  // (only works on gke)
    88  // getLatestGKEVersion will return newest validMasterVersions.
    89  // Pass in releasePrefix to get latest valid version of a specific release.
    90  // Empty releasePrefix means use latest across all available releases.
    91  func getLatestGKEVersion(project, zone, region, releasePrefix string) (string, error) {
    92  	cmd := []string{
    93  		"container",
    94  		"get-server-config",
    95  		fmt.Sprintf("--project=%v", project),
    96  		"--format=value(validMasterVersions)",
    97  	}
    98  
    99  	// --gkeCommandGroup is from gke.go
   100  	if *gkeCommandGroup != "" {
   101  		cmd = append([]string{*gkeCommandGroup}, cmd...)
   102  	}
   103  
   104  	// zone can be empty for regional cluster
   105  	if zone != "" {
   106  		cmd = append(cmd, fmt.Sprintf("--zone=%v", zone))
   107  	} else if region != "" {
   108  		cmd = append(cmd, fmt.Sprintf("--region=%v", region))
   109  	}
   110  
   111  	res, err := control.Output(exec.Command("gcloud", cmd...))
   112  	if err != nil {
   113  		return "", err
   114  	}
   115  	versions := strings.Split(strings.TrimSpace(string(res)), ";")
   116  	latestValid := ""
   117  	for _, version := range versions {
   118  		if strings.HasPrefix(version, releasePrefix) {
   119  			latestValid = version
   120  			break
   121  		}
   122  	}
   123  	if latestValid == "" {
   124  		return "", fmt.Errorf("cannot find valid gke release %s version from: %s", releasePrefix, string(res))
   125  	}
   126  	return "v" + latestValid, nil
   127  }
   128  
   129  // gcsWrite uploads contents to the dest location in GCS.
   130  // It currently shells out to gsutil, but this could change in future.
   131  func gcsWrite(dest string, contents []byte) error {
   132  	f, err := ioutil.TempFile("", "")
   133  	if err != nil {
   134  		return fmt.Errorf("error creating temp file: %v", err)
   135  	}
   136  
   137  	defer func() {
   138  		if err := os.Remove(f.Name()); err != nil {
   139  			log.Printf("error removing temp file: %v", err)
   140  		}
   141  	}()
   142  
   143  	if _, err := f.Write(contents); err != nil {
   144  		return fmt.Errorf("error writing temp file: %v", err)
   145  	}
   146  
   147  	if err := f.Close(); err != nil {
   148  		return fmt.Errorf("error closing temp file: %v", err)
   149  	}
   150  
   151  	return control.FinishRunning(exec.Command("gsutil", "cp", f.Name(), dest))
   152  }