From e42ca5787d65b4e9839eedc2c5a5e29d2e6ab728 Mon Sep 17 00:00:00 2001 From: Victor Marmol Date: Mon, 16 Feb 2015 19:28:56 -0800 Subject: [PATCH] Don't use screen to run cAdvisor in the background. Some distros don't have screen. Here we wait for cAdvisor to come up before continuing. --- integration/common/gce.go | 50 +++++++++++++++++++++++ integration/framework/framework.go | 27 +----------- integration/runner/{main.go => runner.go} | 48 +++++++++++++++++++--- 3 files changed, 94 insertions(+), 31 deletions(-) create mode 100644 integration/common/gce.go rename integration/runner/{main.go => runner.go} (67%) diff --git a/integration/common/gce.go b/integration/common/gce.go new file mode 100644 index 00000000..c563a5b7 --- /dev/null +++ b/integration/common/gce.go @@ -0,0 +1,50 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + "os/exec" + "regexp" + + "github.com/GoogleCloudPlatform/gcloud-golang/compute/metadata" +) + +var gceInternalIpRegexp = regexp.MustCompile(" +ip +\\| +([0-9.:]+) +") +var gceExternalIpRegexp = regexp.MustCompile("external-ip +\\| +([0-9.:]+) +") + +// Gets the IP of the specified GCE instance. +func GetGceIp(hostname string) (string, error) { + if hostname == "localhost" { + return "127.0.0.1", nil + } + + out, err := exec.Command("gcutil", "getinstance", hostname).CombinedOutput() + if err != nil { + return "", err + } + + // Use the internal IP within GCE and the external one outside. + var matches []string + if metadata.OnGCE() { + matches = gceInternalIpRegexp.FindStringSubmatch(string(out)) + } else { + matches = gceExternalIpRegexp.FindStringSubmatch(string(out)) + } + if len(matches) == 0 { + return "", fmt.Errorf("failed to find IP from output %q", string(out)) + } + return matches[1], nil +} diff --git a/integration/framework/framework.go b/integration/framework/framework.go index 112795dc..5d97b950 100644 --- a/integration/framework/framework.go +++ b/integration/framework/framework.go @@ -18,14 +18,13 @@ import ( "flag" "fmt" "os/exec" - "regexp" "strings" "testing" "time" - "github.com/GoogleCloudPlatform/gcloud-golang/compute/metadata" "github.com/golang/glog" "github.com/google/cadvisor/client" + "github.com/google/cadvisor/integration/common" ) var host = flag.String("host", "localhost", "Address of the host being tested") @@ -70,7 +69,7 @@ func New(t *testing.T) Framework { hostname := *host if hostname != "localhost" { gceInstanceName = hostname - gceIp, err := getGceIp(hostname) + gceIp, err := common.GetGceIp(hostname) if err == nil { hostname = gceIp } @@ -128,28 +127,6 @@ func (self HostInfo) FullHost() string { return fmt.Sprintf("http://%s:%d/", self.Host, self.Port) } -var gceInternalIpRegexp = regexp.MustCompile(" +ip +\\| +([0-9.:]+) +") -var gceExternalIpRegexp = regexp.MustCompile("external-ip +\\| +([0-9.:]+) +") - -func getGceIp(hostname string) (string, error) { - out, err := exec.Command("gcutil", "getinstance", hostname).CombinedOutput() - if err != nil { - return "", err - } - - // Use the internal IP within GCE and the external one outside. - var matches []string - if metadata.OnGCE() { - matches = gceInternalIpRegexp.FindStringSubmatch(string(out)) - } else { - matches = gceExternalIpRegexp.FindStringSubmatch(string(out)) - } - if len(matches) == 0 { - return "", fmt.Errorf("failed to find IP from output %q", string(out)) - } - return matches[1], nil -} - func (self *realFramework) T() *testing.T { return self.t } diff --git a/integration/runner/main.go b/integration/runner/runner.go similarity index 67% rename from integration/runner/main.go rename to integration/runner/runner.go index 77102dc8..c70b2053 100644 --- a/integration/runner/main.go +++ b/integration/runner/runner.go @@ -17,16 +17,22 @@ package main import ( "flag" "fmt" + "net/http" "os" "os/exec" "path" + "strconv" "time" "github.com/golang/glog" + "github.com/google/cadvisor/integration/common" ) const cadvisorBinary = "cadvisor" +var cadvisorTimeout = flag.Duration("cadvisor_timeout", 15*time.Second, "Time to wait for cAdvisor to come up on the remote host") +var port = flag.Int("port", 8080, "Port in which to start cAdvisor in the remote host") + func RunCommand(cmd string, args ...string) error { output, err := exec.Command(cmd, args...).CombinedOutput() if err != nil { @@ -78,12 +84,16 @@ func Run() error { } // TODO(vmarmol): Get logs in case of failures. - // Start it. + // Start cAdvisor. glog.Infof("Running cAdvisor on the remote host...") - err = RunCommand("gcutil", "ssh", host, "sudo", "screen", "-d", "-m", path.Join(testDir, cadvisorBinary), "--logtostderr", "&>", "/dev/null") - if err != nil { - return err - } + portStr := strconv.Itoa(*port) + errChan := make(chan error) + go func() { + err = RunCommand("gcutil", "ssh", host, "sudo", path.Join(testDir, cadvisorBinary), "--port", portStr, "--logtostderr", "&>", "/dev/null") + if err != nil { + errChan <- err + } + }() defer func() { err := RunCommand("gcutil", "ssh", host, "sudo", "killall", cadvisorBinary) if err != nil { @@ -91,9 +101,35 @@ func Run() error { } }() + ipAddress, err := common.GetGceIp(host) + if err != nil { + return err + } + + // Wait for cAdvisor to come up. + endTime := time.Now().Add(*cadvisorTimeout) + done := false + for endTime.After(time.Now()) && !done { + select { + case err := <-errChan: + // Quit early if there was an error. + return err + case <-time.After(500 * time.Millisecond): + // Stop waiting when cAdvisor is healthy.. + resp, err := http.Get(fmt.Sprintf("http://%s:%s/healthz", ipAddress, portStr)) + if err == nil && resp.StatusCode == http.StatusOK { + done = true + break + } + } + } + if !done { + return fmt.Errorf("timed out waiting for cAdvisor to come up at host %q", host) + } + // Run the tests. glog.Infof("Running integration tests targeting remote host...") - err = RunCommand("godep", "go", "test", "github.com/google/cadvisor/integration/tests/...", "--host", host) + err = RunCommand("godep", "go", "test", "github.com/google/cadvisor/integration/tests/...", "--host", host, "--port", portStr) if err != nil { return err }