Node e2e can run tests against GCE images based on a regex.

It can run tests against multiple existing images that match a regex.
GCI images will be using a regex.

Signed-off-by: Vishnu kannan <vishnuk@google.com>
This commit is contained in:
Vishnu kannan 2016-07-29 17:55:01 -07:00
parent a40d2cd92e
commit 2f6514bd63
4 changed files with 78 additions and 12 deletions

View File

@ -39,7 +39,6 @@ fi
function get_latest_gci_image() {
# GCI milestone to use
# Update the GCI image in test/e2e_node/jenkins/image-config.yaml before updating the milestone here.
GCI_MILESTONE="53"
# First try to find an active (non-deprecated) image on this milestone.

View File

@ -40,7 +40,7 @@ WORKSPACE=${WORKSPACE:-"/tmp/"}
ARTIFACTS=${WORKSPACE}/_artifacts
mkdir -p ${ARTIFACTS}
go run test/e2e_node/runner/run_e2e.go --logtostderr --vmodule=*=2 --ssh-env="gce" \
go run test/e2e_node/runner/run_e2e.go --logtostderr --vmodule=*=4 --ssh-env="gce" \
--zone="$GCE_ZONE" --project="$GCE_PROJECT" --hosts="$GCE_HOSTS" \
--images="$GCE_IMAGES" --image-project="$GCE_IMAGE_PROJECT" \
--image-config-file="$GCE_IMAGE_CONFIG_PATH" --cleanup="$CLEANUP" \

View File

@ -15,7 +15,7 @@ images:
containervm:
image: e2e-node-containervm-v20160321-image
project: kubernetes-node-e2e-images
gci-dev:
image: gci-dev-53-8530-29-0
gci-family:
image_regex: gci-dev-.*
project: google-containers
metadata: "user-data<test/e2e_node/jenkins/gci-init.yaml"

View File

@ -27,6 +27,8 @@ import (
"math/rand"
"net/http"
"os"
"regexp"
"sort"
"strings"
"sync"
"time"
@ -86,9 +88,13 @@ type ImageConfig struct {
}
type GCEImage struct {
Image string `json:"image"`
Project string `json:"project"`
Metadata string `json:"metadata"`
Image string `json:"image, omitempty"`
Project string `json:"project"`
Metadata string `json:"metadata"`
ImageRegex string `json:"image_regex, omitempty"`
// Defaults to using only the latest image. Acceptible values are [0, # of images that match the regex).
// If the number of existing previous images is lesser than what is desired, the test will use that is available.
PreviousImages int `json:"previous_images, omitempty"`
}
type internalImageConfig struct {
@ -128,12 +134,23 @@ func main() {
glog.Fatalf("Could not parse image config file: %v", err)
}
for key, imageConfig := range externalImageConfig.Images {
gceImage := internalGCEImage{
image: imageConfig.Image,
project: imageConfig.Project,
metadata: getImageMetadata(imageConfig.Metadata),
var images []string
if imageConfig.ImageRegex != "" && imageConfig.Image == "" {
images, err = getGCEImages(imageConfig.ImageRegex, imageConfig.Project, imageConfig.PreviousImages)
if err != nil {
glog.Fatalf("Could not retrieve list of images based on image prefix %q: %v", imageConfig.ImageRegex, err)
}
} else {
images = []string{imageConfig.Image}
}
for _, image := range images {
gceImage := internalGCEImage{
image: image,
project: imageConfig.Project,
metadata: getImageMetadata(imageConfig.Metadata),
}
gceImages.images[image] = gceImage
}
gceImages.images[key] = gceImage
}
}
@ -306,6 +323,55 @@ func testHost(host string, deleteFiles bool, junitFilePrefix string, setupNode b
}
}
type imageObj struct {
creationTime time.Time
name string
}
func (io imageObj) string() string {
return fmt.Sprintf("%q created % %q", io.name, io.creationTime.String())
}
type byCreationTime []imageObj
func (a byCreationTime) Len() int { return len(a) }
func (a byCreationTime) Less(i, j int) bool { return a[i].creationTime.After(a[j].creationTime) }
func (a byCreationTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// Returns a list of image names based on regex and number of previous images requested.
func getGCEImages(imageRegex, project string, previousImages int) ([]string, error) {
ilc, err := computeService.Images.List(project).Do()
if err != nil {
return nil, fmt.Errorf("Failed to list images in project %q and zone %q", project, zone)
}
imageObjs := []imageObj{}
imageRe := regexp.MustCompile(imageRegex)
for _, instance := range ilc.Items {
if imageRe.MatchString(instance.Name) {
creationTime, err := time.Parse(time.RFC3339, instance.CreationTimestamp)
if err != nil {
return nil, fmt.Errorf("Failed to parse instance creation timestamp %q: %v", instance.CreationTimestamp, err)
}
io := imageObj{
creationTime: creationTime,
name: instance.Name,
}
glog.V(4).Infof("Found image %q based on regex %q in project %q", io.string(), imageRegex, project)
imageObjs = append(imageObjs, io)
}
}
sort.Sort(byCreationTime(imageObjs))
images := []string{}
for _, imageObj := range imageObjs {
images = append(images, imageObj.name)
previousImages--
if previousImages < 0 {
break
}
}
return images, nil
}
// Provision a gce instance using image and run the tests in archive against the instance.
// Delete the instance afterward.
func testImage(image *internalGCEImage, junitFilePrefix string) *TestResult {
@ -327,6 +393,7 @@ func testImage(image *internalGCEImage, junitFilePrefix string) *TestResult {
// Provision a gce instance using image
func createInstance(image *internalGCEImage) (string, error) {
glog.V(1).Infof("Creating instance %+v", *image)
name := imageToInstanceName(image.image)
i := &compute.Instance{
Name: name,