From 439cb3e74f0d288e10a95d0d610160336a602d94 Mon Sep 17 00:00:00 2001 From: Adam Worrall Date: Tue, 27 Jun 2017 17:11:32 -0700 Subject: [PATCH] Log the OS images used during cluster creation --- test/e2e/e2e.go | 5 ++ test/e2e/framework/google_compute.go | 97 ++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index 8b2158a9999..b1dab7e0979 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -118,6 +118,11 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { framework.Failf("Failed to setup provider config: %v", err) } + switch framework.TestContext.Provider { + case "gce", "gke": + framework.LogClusterImageSources() + } + c, err := framework.LoadClientset() if err != nil { glog.Fatal("Error loading client: ", err) diff --git a/test/e2e/framework/google_compute.go b/test/e2e/framework/google_compute.go index 726726b397a..8b6fbedfe19 100644 --- a/test/e2e/framework/google_compute.go +++ b/test/e2e/framework/google_compute.go @@ -17,8 +17,11 @@ limitations under the License. package framework import ( + "encoding/json" "fmt" + "io/ioutil" "os/exec" + "path/filepath" "regexp" "strings" "time" @@ -96,3 +99,97 @@ func DeleteGCEStaticIP(name string) error { } return nil } + +// Returns master & node image string, or error +func lookupClusterImageSources() (string, string, error) { + // Given args for a gcloud compute command, run it with other args, and return the values, + // whether separated by newlines, commas or semicolons. + gcloudf := func(argv ...string) ([]string, error) { + args := []string{"compute"} + args = append(args, argv...) + args = append(args, "--project", TestContext.CloudConfig.ProjectID, + "--zone", TestContext.CloudConfig.Zone) + outputBytes, err := exec.Command("gcloud", args...).CombinedOutput() + str := strings.Replace(string(outputBytes), ",", "\n", -1) + str = strings.Replace(str, ";", "\n", -1) + lines := strings.Split(str, "\n") + if err != nil { + Logf("lookupDiskImageSources: gcloud error with [%#v]; err:%v", argv, err) + for _, l := range lines { + Logf(" > %s", l) + } + } + return lines, err + } + + // Given a GCE instance, look through its disks, finding one that has a sourceImage + host2image := func(instance string) (string, error) { + // gcloud compute instances describe {INSTANCE} --format="get(disks[].source)" + // gcloud compute disks describe {DISKURL} --format="get(sourceImage)" + disks, err := gcloudf("instances", "describe", instance, "--format=get(disks[].source)") + if err != nil { + return "", err + } else if len(disks) == 0 { + return "", fmt.Errorf("instance %q had no findable disks", instance) + } + // Loop over disks, looking for the boot disk + for _, disk := range disks { + lines, err := gcloudf("disks", "describe", disk, "--format=get(sourceImage)") + if err != nil { + return "", err + } else if len(lines) > 0 && lines[0] != "" { + return lines[0], nil // break, we're done + } + } + return "", fmt.Errorf("instance %q had no disk with a sourceImage", instance) + } + + // gcloud compute instance-groups list-instances {GROUPNAME} --format="get(instance)" + nodeName := "" + instGroupName := strings.Split(TestContext.CloudConfig.NodeInstanceGroup, ",")[0] + if lines, err := gcloudf("instance-groups", "list-instances", instGroupName, "--format=get(instance)"); err != nil { + return "", "", err + } else if len(lines) == 0 { + return "", "", fmt.Errorf("no instances inside instance-group %q", instGroupName) + } else { + nodeName = lines[0] + } + + nodeImg, err := host2image(nodeName) + if err != nil { + return "", "", err + } + frags := strings.Split(nodeImg, "/") + nodeImg = frags[len(frags)-1] + + masterName := TestContext.CloudConfig.MasterName + masterImg, err := host2image(masterName) + if err != nil { + return "", "", err + } + frags = strings.Split(masterImg, "/") + masterImg = frags[len(frags)-1] + + return masterImg, nodeImg, nil +} + +func LogClusterImageSources() { + masterImg, nodeImg, err := lookupClusterImageSources() + if err != nil { + Logf("Cluster image sources lookup failed: %v\n", err) + return + } + Logf("cluster-master-image: %s", masterImg) + Logf("cluster-node-image: %s", nodeImg) + + images := map[string]string{ + "master_os_image": masterImg, + "node_os_image": nodeImg, + } + + outputBytes, _ := json.MarshalIndent(images, "", " ") + filePath := filepath.Join(TestContext.OutputDir, "images.json") + if err := ioutil.WriteFile(filePath, outputBytes, 0644); err != nil { + Logf("cluster images sources, could not write to %q: %v", filePath, err) + } +}