Auto-update dependencies (#79)

Produced via:
  `dep ensure -update knative.dev/test-infra knative.dev/pkg`
/assign mattmoor
This commit is contained in:
mattmoor-sockpuppet 2019-08-22 07:13:35 -07:00 committed by Knative Prow Robot
parent c4ccaeb5a0
commit d7f2dc2e82
15 changed files with 649 additions and 46 deletions

8
Gopkg.lock generated
View File

@ -927,7 +927,7 @@
[[projects]]
branch = "master"
digest = "1:b9a2a90a672cca14c7353eff529b8375db18878fd03fff30a63cb5500decdc08"
digest = "1:5dddb45857ff59292216934b6f39415befab65246afac26ba14976e3ec11a343"
name = "knative.dev/pkg"
packages = [
"apis",
@ -946,18 +946,18 @@
"metrics/metricskey",
]
pruneopts = "T"
revision = "c11c79155fa4be834735d1d0cbcafad88b16be69"
revision = "9f6e5334c25aeebd862b19cb6715f9fe5aa56467"
[[projects]]
branch = "master"
digest = "1:305af75fc194c059ae710a75276ca8f1870c959214b18ed33f7ef8671995947f"
digest = "1:a68a49f889453ee0abab8d32ceaa19c12a1e86c7919e9cecb3d5ceac6aac199c"
name = "knative.dev/test-infra"
packages = [
"scripts",
"tools/dep-collector",
]
pruneopts = "UT"
revision = "f3fe0bcc30693df8e3c9616358b16045efb9ed10"
revision = "d2746f8b9470e8c8452a997e95190aba5320678a"
[solve-meta]
analyzer-name = "dep"

41
vendor/knative.dev/pkg/Gopkg.lock generated vendored
View File

@ -223,6 +223,23 @@
pruneopts = "NUT"
revision = "c3068f13fcc3961fd05f96f13c8250e350db4209"
[[projects]]
digest = "1:3efb665a5beaa0266ff287cdb58dff8a966631000e9f8ad8d832a288b90ca247"
name = "github.com/google/mako"
packages = [
"clients/proto/analyzers/threshold_analyzer_go_proto",
"clients/proto/analyzers/utest_analyzer_go_proto",
"clients/proto/analyzers/window_deviation_go_proto",
"helpers/go/quickstore",
"helpers/proto/quickstore/quickstore_go_proto",
"internal/go/common",
"internal/quickstore_microservice/proto/quickstore_go_proto",
"spec/proto/mako_go_proto",
]
pruneopts = "NUT"
revision = "d56a6e811df75f8e4d6e7c256d25acf19ef16d03"
version = "v0.0.0-rc.4"
[[projects]]
digest = "1:ab3ec1fe3e39bac4b3ab63390767766622be35b7cab03f47f787f9ec60522a53"
name = "github.com/google/uuid"
@ -699,9 +716,13 @@
[[projects]]
branch = "master"
digest = "1:9b9245bd124d95af7072487cd1e5861174b859ebc31cbe9fbab3b88456701485"
digest = "1:bcfc1adc3202f2ff120bc4686c613c8f34af0f9e3de49b55d3bbecd70dc6651b"
name = "google.golang.org/api"
packages = [
"container/v1",
"gensupport",
"googleapi",
"googleapi/internal/uritemplates",
"googleapi/transport",
"internal",
"iterator",
@ -1184,14 +1205,11 @@
[[projects]]
branch = "master"
digest = "1:013d8728ceab59db2a90db464dc0d3c1f677bdf95f974fed26fe6094b5504cf2"
digest = "1:df1c1cf6d2c9ca0781705ef095cb15e06f777cddb493775aad41b72f79867d7a"
name = "k8s.io/test-infra"
packages = [
"boskos",
"boskos/client",
"boskos/common",
"boskos/crds",
"boskos/ranch",
"boskos/storage",
]
pruneopts = "NUT"
@ -1199,14 +1217,14 @@
[[projects]]
branch = "master"
digest = "1:39bb1014c454fbf9d8f4eab62a44fcf8d3ade774e2b42015e533e5d9f3fe23d9"
digest = "1:305af75fc194c059ae710a75276ca8f1870c959214b18ed33f7ef8671995947f"
name = "knative.dev/test-infra"
packages = [
"scripts",
"tools/dep-collector",
]
pruneopts = "UT"
revision = "d65201fadb82dbdc5713f9ba9a1313150c7aa9b5"
revision = "f3fe0bcc30693df8e3c9616358b16045efb9ed10"
[[projects]]
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"
@ -1229,8 +1247,13 @@
"github.com/evanphx/json-patch",
"github.com/ghodss/yaml",
"github.com/golang/glog",
"github.com/golang/protobuf/proto",
"github.com/google/go-cmp/cmp",
"github.com/google/go-cmp/cmp/cmpopts",
"github.com/google/mako/clients/proto/analyzers/threshold_analyzer_go_proto",
"github.com/google/mako/helpers/go/quickstore",
"github.com/google/mako/helpers/proto/quickstore/quickstore_go_proto",
"github.com/google/mako/spec/proto/mako_go_proto",
"github.com/google/uuid",
"github.com/gorilla/websocket",
"github.com/markbates/inflect",
@ -1253,7 +1276,10 @@
"go.uber.org/zap",
"go.uber.org/zap/zapcore",
"go.uber.org/zap/zaptest",
"golang.org/x/net/context",
"golang.org/x/oauth2/google",
"golang.org/x/sync/errgroup",
"google.golang.org/api/container/v1",
"gopkg.in/yaml.v2",
"k8s.io/api/admission/v1beta1",
"k8s.io/api/admissionregistration/v1beta1",
@ -1323,7 +1349,6 @@
"k8s.io/gengo/namer",
"k8s.io/gengo/types",
"k8s.io/klog",
"k8s.io/test-infra/boskos",
"k8s.io/test-infra/boskos/client",
"k8s.io/test-infra/boskos/common",
"knative.dev/test-infra/scripts",

View File

@ -8,7 +8,7 @@ required = [
"k8s.io/code-generator/cmd/client-gen",
"k8s.io/code-generator/cmd/lister-gen",
"k8s.io/code-generator/cmd/informer-gen",
"k8s.io/test-infra/boskos",
"google.golang.org/api/container/v1",
"github.com/evanphx/json-patch",
"knative.dev/test-infra/scripts",
"knative.dev/test-infra/tools/dep-collector",

View File

@ -0,0 +1,7 @@
# Mako
[Mako](https://github.com/google/mako) is an open source project for performance testing in Knative.
It offers capacities like data storage, charting, statistical aggregation and automated regression analysis.
This folder contains common code that can be used by all Knative projects, with which we can follow the
same process to set up Mako and collaborate.

View File

@ -0,0 +1,35 @@
/*
Copyright 2019 The Knative Authors
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 mako
import (
"github.com/golang/protobuf/proto"
tpb "github.com/google/mako/clients/proto/analyzers/threshold_analyzer_go_proto"
mpb "github.com/google/mako/spec/proto/mako_go_proto"
)
// NewCrossRunConfig returns a config that can be used in ThresholdAnalyzer.
// By using it, the Analyzer will only fail if there are xx continuous runs that cross the threshold.
func NewCrossRunConfig(runCount int32, tags ...string) *tpb.CrossRunConfig {
return &tpb.CrossRunConfig{
RunInfoQueryList: []*mpb.RunInfoQuery{{
Limit: proto.Int32(runCount),
Tags: tags,
}},
MinRunCount: proto.Int32(runCount),
}
}

View File

@ -0,0 +1,71 @@
/*
Copyright 2019 The Knative Authors
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 mako
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"github.com/golang/protobuf/proto"
mpb "github.com/google/mako/spec/proto/mako_go_proto"
)
const koDataPathEnvName = "KO_DATA_PATH"
// MustGetBenchmark wraps getBenchmark in log.Fatalf
func MustGetBenchmark() *string {
b, err := getBenchmark()
if err != nil {
log.Fatalf("unable to determine benchmark_key: %v", err)
}
return b
}
// getBenchmark fetches the appropriate benchmark_key for this configured environment.
func getBenchmark() (*string, error) {
// Figure out what environment we're running in from the Mako configmap.
env, err := getEnvironment()
if err != nil {
return nil, err
}
// Read the Mako config file for this environment.
data, err := readConfigFromKoData(env)
if err != nil {
return nil, err
}
// Parse the Mako config file.
bi := &mpb.BenchmarkInfo{}
if err := proto.UnmarshalText(string(data), bi); err != nil {
return nil, err
}
// Return the benchmark_key from this environment's config file.
return bi.BenchmarkKey, nil
}
// readConfigFromKoData reads the named config file from kodata.
func readConfigFromKoData(environment string) ([]byte, error) {
koDataPath := os.Getenv(koDataPathEnvName)
if koDataPath == "" {
return nil, fmt.Errorf("%q does not exist or is empty", koDataPathEnvName)
}
fullFilename := filepath.Join(koDataPath, environment+".config")
return ioutil.ReadFile(fullFilename)
}

View File

@ -0,0 +1,60 @@
/*
Copyright 2019 The Knative Authors
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 mako
import (
"strings"
corev1 "k8s.io/api/core/v1"
)
const (
// ConfigName is the name of the config map for mako options.
ConfigName = "config-mako"
)
// Config defines the mako configuration options.
type Config struct {
// Environment holds the name of the environement,
// where the test runs, e.g. `dev`.
Environment string
// List of additional tags to apply to the run.
AdditionalTags []string
}
// NewConfigFromMap creates a Config from the supplied map
func NewConfigFromMap(data map[string]string) (*Config, error) {
lc := &Config{
Environment: "dev",
AdditionalTags: []string{},
}
if raw, ok := data["environment"]; ok {
lc.Environment = raw
}
if raw, ok := data["additionalTags"]; ok && raw != "" {
lc.AdditionalTags = strings.Split(raw, ",")
}
return lc, nil
}
// NewConfigFromConfigMap creates a Config from the supplied ConfigMap
func NewConfigFromConfigMap(configMap *corev1.ConfigMap) (*Config, error) {
return NewConfigFromMap(configMap.Data)
}

View File

@ -0,0 +1,52 @@
/*
Copyright 2019 The Knative Authors
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 mako
import (
"log"
"path/filepath"
"knative.dev/pkg/configmap"
)
// TODO: perhaps cache the loaded CM.
// MustGetTags returns the additional tags from the configmap, or dies.
func MustGetTags() []string {
makoCM, err := configmap.Load(filepath.Join("/etc", ConfigName))
if err != nil {
log.Fatalf("unable to load configmap: %v", err)
}
cfg, err := NewConfigFromMap(makoCM)
if err != nil {
log.Fatalf("unable to parse configmap: %v", err)
}
return cfg.AdditionalTags
}
// getEnvironment fetches the Mako config environment to which this cluster should publish.
func getEnvironment() (string, error) {
makoCM, err := configmap.Load(filepath.Join("/etc", ConfigName))
if err != nil {
return "", err
}
cfg, err := NewConfigFromMap(makoCM)
if err != nil {
return "", err
}
return cfg.Environment, nil
}

View File

@ -0,0 +1,96 @@
/*
Copyright 2019 The Knative Authors
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 mako
import (
"context"
"log"
"runtime"
"strings"
"cloud.google.com/go/compute/metadata"
"knative.dev/pkg/injection/clients/kubeclient"
"github.com/google/mako/helpers/go/quickstore"
qpb "github.com/google/mako/helpers/proto/quickstore/quickstore_go_proto"
"k8s.io/client-go/rest"
"knative.dev/pkg/changeset"
"knative.dev/pkg/controller"
"knative.dev/pkg/injection"
)
const (
// sidecarAddress is the address of the Mako sidecar to which we locally
// write results, and it authenticates and publishes them to Mako after
// assorted preprocessing.
sidecarAddress = "localhost:9813"
)
// EscapeTag replaces characters that Mako doesn't accept with ones it does.
func EscapeTag(tag string) string {
return strings.ReplaceAll(tag, ".", "_")
}
// Setup sets up the mako client for the provided benchmarkKey.
// It will add a few common tags and allow each benchmark to add custm tags as well.
// It returns the mako client handle to store metrics, a method to close the connection
// to mako server once done and error in case of failures.
func Setup(ctx context.Context, extraTags ...string) (context.Context, *quickstore.Quickstore, func(context.Context), error) {
tags := append(MustGetTags(), extraTags...)
// Get the commit of the benchmarks
commitID, err := changeset.Get()
if err != nil {
return nil, nil, nil, err
}
// Setup a deployment informer, so that we can use the lister to track
// desired and available pod counts.
cfg, err := rest.InClusterConfig()
if err != nil {
return nil, nil, nil, err
}
ctx, informers := injection.Default.SetupInformers(ctx, cfg)
if err := controller.StartInformers(ctx.Done(), informers...); err != nil {
return nil, nil, nil, err
}
// Get the Kubernetes version from the API server.
version, err := kubeclient.Get(ctx).Discovery().ServerVersion()
if err != nil {
return nil, nil, nil, err
}
// Get GCP project ID as a tag.
if projectID, err := metadata.ProjectID(); err != nil {
log.Printf("GCP project ID is not available: %v", err)
} else {
tags = append(tags, "project-id="+EscapeTag(projectID))
}
qs, qclose, err := quickstore.NewAtAddress(ctx, &qpb.QuickstoreInput{
BenchmarkKey: MustGetBenchmark(),
Tags: append(tags,
"commit="+commitID,
"kubernetes="+EscapeTag(version.String()),
EscapeTag(runtime.Version()),
),
}, sidecarAddress)
if err != nil {
return nil, nil, nil, err
}
return ctx, qs, qclose, nil
}

View File

@ -0,0 +1,47 @@
# Copyright 2019 The Knative Authors
#
# 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
#
# https://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.
apiVersion: v1
kind: ConfigMap
metadata:
name: config-mako
data:
_example: |
################################
# #
# EXAMPLE CONFIGURATION #
# #
################################
# This block is not actually functional configuration,
# but serves to illustrate the available configuration
# options and document them in a way that is accessible
# to users that `kubectl edit` this config map.
#
# These sample configuration options may be copied out of
# this example block and unindented to be in the data block
# to actually change the configuration.
# The Mako environment in which we are running.
# Only our performance automation should run in "prod", but
# there should be a "dev" environment with a fairly broad
# write ACL. Users can also develop against custom configurations
# by adding `foo.config` under their benchmark's kodata directory.
environment: dev
# Additional tags to tag the runs. These tags are added
# to the list that the binary itself publishes (Kubernetes version, etc).
# It is a comma separated list of tags.
additionalTags: "key=value,absolute"

View File

@ -0,0 +1,26 @@
/*
Copyright 2019 The Knative Authors
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 mako
import (
"time"
)
// XTime converts a time.Time into a Mako x-axis compatible timestamp.
func XTime(t time.Time) float64 {
return float64(t.UnixNano()) / (1000.0 * 1000.0)
}

View File

@ -18,25 +18,77 @@ package clustermanager
import (
"fmt"
"log"
"strings"
"time"
"knative.dev/pkg/testutils/clustermanager/boskos"
"knative.dev/pkg/testutils/common"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"google.golang.org/api/container/v1"
)
const (
DefaultGKENumNodes = 1
DefaultGKENodeType = "n1-standard-4"
DefaultGKERegion = "us-central1"
DefaultGKEZone = ""
regionEnv = "E2E_CLUSTER_REGION"
backupRegionEnv = "E2E_CLUSTER_BACKUP_REGIONS"
)
var (
DefaultGKEBackupRegions = []string{"us-west1", "us-east1"}
// This is an arbitrary number determined based on past experience
creationTimeout = 20 * time.Minute
)
// GKEClient implements Client
type GKEClient struct {
}
// GKERequest contains all requests collected for cluster creation
type GKERequest struct {
NumNodes int64
NodeType string
Region string
Zone string
BackupRegions []string
}
// GKECluster implements ClusterOperations
type GKECluster struct {
Request *GKERequest
// Project might be GKE specific, so put it here
Project *string
// NeedCleanup tells whether the cluster needs to be deleted afterwards
// This probably should be part of task wrapper's logic
NeedCleanup bool
// TODO: evaluate returning "google.golang.org/api/container/v1.Cluster" when implementing the creation logic
Cluster *string
Cluster *container.Cluster
operations GKESDKOperations
}
// GKESDKOperations wraps GKE SDK related functions
type GKESDKOperations interface {
create(string, string, *container.CreateClusterRequest) (*container.Operation, error)
get(string, string, string) (*container.Cluster, error)
}
// GKESDKClient Implement GKESDKOperations
type GKESDKClient struct {
*container.Service
}
func (gsc *GKESDKClient) create(project, location string, rb *container.CreateClusterRequest) (*container.Operation, error) {
parent := fmt.Sprintf("projects/%s/locations/%s", project, location)
return gsc.Projects.Locations.Clusters.Create(parent, rb).Context(context.Background()).Do()
}
func (gsc *GKESDKClient) get(project, location, cluster string) (*container.Cluster, error) {
clusterFullPath := fmt.Sprintf("projects/%s/locations/%s/clusters/%s", project, location, cluster)
return gsc.Projects.Locations.Clusters.Get(clusterFullPath).Context(context.Background()).Do()
}
// Setup sets up a GKECluster client.
@ -44,10 +96,31 @@ type GKECluster struct {
// nodeType: default to n1-standard-4 if not provided
// region: default to regional cluster if not provided, and use default backup regions
// zone: default is none, must be provided together with region
func (gs *GKEClient) Setup(numNodes *int, nodeType *string, region *string, zone *string, project *string) (ClusterOperations, error) {
gc := &GKECluster{}
// check for local run
if nil != project { // if project is supplied, use it and create cluster
func (gs *GKEClient) Setup(numNodes *int64, nodeType *string, region *string, zone *string, project *string) (ClusterOperations, error) {
var err error
gc := &GKECluster{
Request: &GKERequest{
NumNodes: DefaultGKENumNodes,
NodeType: DefaultGKENodeType,
Region: DefaultGKERegion,
Zone: DefaultGKEZone,
BackupRegions: DefaultGKEBackupRegions},
}
ctx := context.Background()
c, err := google.DefaultClient(ctx, container.CloudPlatformScope)
if nil != err {
return nil, fmt.Errorf("failed create google client: '%v'", err)
}
containerService, err := container.New(c)
if nil != err {
return nil, fmt.Errorf("failed create container service: '%v'", err)
}
gc.operations = &GKESDKClient{containerService}
if nil != project { // use provided project and create cluster
gc.Project = project
gc.NeedCleanup = true
} else if err := gc.checkEnvironment(); nil != err {
@ -55,17 +128,38 @@ func (gs *GKEClient) Setup(numNodes *int, nodeType *string, region *string, zone
} else if nil != gc.Cluster { // return if Cluster was already set by kubeconfig
return gc, nil
}
// check for Prow
if common.IsProw() {
boskosRes, err := boskos.AcquireGKEProject(nil)
if nil != err {
return nil, fmt.Errorf("failed acquire boskos project: '%v'", err)
if nil == gc.Cluster {
if common.IsProw() {
project, err := boskos.AcquireGKEProject(nil)
if nil != err {
return nil, fmt.Errorf("failed acquire boskos project: '%v'", err)
}
gc.Project = &project.Name
}
if nil != numNodes {
gc.Request.NumNodes = *numNodes
}
if nil != nodeType {
gc.Request.NodeType = *nodeType
}
if nil != region {
gc.Request.Region = *region
}
if "" != common.GetOSEnv(regionEnv) {
gc.Request.Region = common.GetOSEnv(regionEnv)
}
if "" != common.GetOSEnv(backupRegionEnv) {
gc.Request.BackupRegions = strings.Split(common.GetOSEnv(backupRegionEnv), " ")
}
if nil != zone {
gc.Request.Zone = *zone
gc.Request.BackupRegions = make([]string, 0)
}
gc.Project = &boskosRes.Name
}
if nil == gc.Project || "" == *gc.Project {
return nil, fmt.Errorf("gcp project must be set")
}
log.Printf("use project '%s' for running test", *gc.Project)
return gc, nil
}
@ -74,14 +168,87 @@ func (gc *GKECluster) Provider() string {
return "gke"
}
// Acquire gets existing cluster or create a new one
// Acquire gets existing cluster or create a new one, the creation logic
// contains retries in BackupRegions. Default creating cluster
// in us-central1, and default BackupRegions are us-west1 and us-east1. If
// Region or Zone is provided then there is no retries
func (gc *GKECluster) Acquire() error {
var err error
// Check if using existing cluster
if nil != gc.Cluster {
return nil
}
// TODO: Perform GKE specific cluster creation logics
return nil
// Perform GKE specific cluster creation logics
clusterName, err := getResourceName(ClusterResource)
if nil != err {
return fmt.Errorf("failed getting cluster name: '%v'", err)
}
regions := []string{gc.Request.Region}
for _, br := range gc.Request.BackupRegions {
exist := false
for _, region := range regions {
if br == region {
exist = true
}
}
if !exist {
regions = append(regions, br)
}
}
var cluster *container.Cluster
for i, region := range regions {
rb := &container.CreateClusterRequest{
Cluster: &container.Cluster{
Name: clusterName,
InitialNodeCount: gc.Request.NumNodes,
NodeConfig: &container.NodeConfig{
MachineType: gc.Request.NodeType,
},
},
ProjectId: *gc.Project,
}
log.Printf("Creating cluster in %s", getClusterLocation(region, gc.Request.Zone))
_, err = gc.operations.create(*gc.Project, getClusterLocation(region, gc.Request.Zone), rb)
if nil == err {
// The process above doesn't seem to wait, wait for it
log.Printf("Waiting for cluster creation")
timeout := time.After(creationTimeout)
tick := time.Tick(50 * time.Millisecond)
for {
select {
// Got a timeout! fail with a timeout error
case <-timeout:
err = fmt.Errorf("timed out waiting for cluster creation")
break
case <-tick:
cluster, err = gc.operations.get(*gc.Project, getClusterLocation(region, gc.Request.Zone), clusterName)
}
if err != nil || cluster.Status == "RUNNING" {
break
}
if cluster.Status != "PROVISIONING" {
err = fmt.Errorf("cluster in bad state: '%s'", cluster.Status)
break
}
}
}
if nil != err {
errMsg := fmt.Sprintf("error creating cluster: '%v'", err)
// TODO(chaodaiG): catch specific errors as we know what the error look like for stockout etc.
if len(regions) != i+1 {
errMsg = fmt.Sprintf("%s. Retry another region '%s' for cluster creation", errMsg, regions[i+1])
}
log.Printf(errMsg)
} else {
log.Printf("cluster creation succeeded")
gc.Cluster = cluster
break
}
}
return err
}
// Delete deletes a GKE cluster
@ -97,19 +264,28 @@ func (gc *GKECluster) Delete() error {
// and sets up gc.Project and gc.Cluster properly, otherwise fail it.
// if project can be derived from gcloud, sets it up as well
func (gc *GKECluster) checkEnvironment() error {
var err error
// if kubeconfig is configured, use it
output, err := common.StandardExec("kubectl", "config", "current-context")
if nil == err {
// output should be in the form of gke_PROJECT_REGION_CLUSTER
parts := strings.Split(string(output), "_")
if len(parts) != 4 {
return fmt.Errorf("kubectl current-context is malformed: '%s'", string(output))
currentContext := strings.TrimSpace(string(output))
if strings.HasPrefix(currentContext, "gke_") {
// output should be in the form of gke_PROJECT_REGION_CLUSTER
parts := strings.Split(currentContext, "_")
if len(parts) != 4 { // fall through with warning
log.Printf("WARNING: ignoring kubectl current-context since it's malformed: '%s'", currentContext)
} else {
log.Printf("kubeconfig isn't empty, uses this cluster for running tests: %s", currentContext)
gc.Project = &parts[1]
gc.Cluster, err = gc.operations.get(*gc.Project, parts[2], parts[3])
if nil != err {
return fmt.Errorf("couldn't find cluster %s in %s in %s, does it exist? %v", parts[3], parts[1], parts[2], err)
}
return nil
}
}
gc.Project = &parts[1]
gc.Cluster = &parts[3]
return nil
}
if string(output) != "" {
if nil != err && len(output) > 0 {
// this is unexpected error, should shout out directly
return fmt.Errorf("failed running kubectl config current-context: '%s'", string(output))
}

View File

@ -51,3 +51,10 @@ func getResourceName(rt ResourceType) (string, error) {
}
return resName, nil
}
func getClusterLocation(region, zone string) string {
if "" != zone {
region = fmt.Sprintf("%s-%s", region, zone)
}
return region
}

View File

@ -288,14 +288,10 @@ function create_test_cluster_with_retries() {
[[ "$(get_test_return_code)" == "0" ]] && return 0
# Retry if cluster creation failed because of:
# - stockout (https://github.com/knative/test-infra/issues/592)
# - latest GKE not available in this region/zone yet
# (https://github.com/knative/test-infra/issues/694)
# - cluster created but some nodes are unhealthy
# (https://github.com/knative/test-infra/issues/1291)
# - latest GKE not available in this region/zone yet (https://github.com/knative/test-infra/issues/694)
[[ -z "$(grep -Fo 'does not have enough resources available to fulfill' ${cluster_creation_log})" \
&& -z "$(grep -Fo 'ResponseError: code=400, message=No valid versions with the prefix' ${cluster_creation_log})" \
&& -z "$(grep -Po 'ResponseError: code=400, message=Master version "[0-9a-z\-\.]+" is unsupported' ${cluster_creation_log})" ]] \
&& -z "$(grep -Po '[0-9]+ nodes out of [0-9]+ are unhealthy' ${cluster_creation_log})" ]] \
&& return 1
done
done

View File

@ -172,14 +172,19 @@ function default_build_test_runner() {
# Get all build tags in go code (ignore /vendor)
local tags="$(grep -r '// +build' . \
| grep -v '^./vendor/' | cut -f3 -d' ' | sort | uniq | tr '\n' ' ')"
if [[ -n "${tags}" ]]; then
errors=""
if ! capture_output "${report}" go test -run=^$ -tags="${tags}" ./... ; then
local tagged_pkgs="$(grep -r '// +build' . \
| grep -v '^./vendor/' | grep ":// +build " | cut -f1 -d: | xargs dirname | sort | uniq | tr '\n' ' ')"
for pkg in ${tagged_pkgs}; do
# `go test -c` lets us compile the tests but do not run them.
if ! capture_output "${report}" go test -c -tags="${tags}" ${pkg} ; then
failed=1
# Consider an error message everything that's not a successful test result.
errors_go2="$(grep -v '^\(ok\|\?\)\s\+\(github\.com\|knative\.dev\)/' "${report}")"
errors_go2+="$(grep -v '^\(ok\|\?\)\s\+\(github\.com\|knative\.dev\)/' "${report}")"
fi
fi
# Remove unused generated binary, if any.
rm -f e2e.test
done
local errors_go="$(echo -e "${errors_go1}\n${errors_go2}" | uniq)"
create_junit_xml _build_tests Build_Go "${errors_go}"
if [[ -f ./hack/verify-codegen.sh ]]; then