vendor update for CSI 0.3.0

This commit is contained in:
gman
2018-07-18 16:47:22 +02:00
parent 6f484f92fc
commit 8ea659f0d5
6810 changed files with 438061 additions and 193861 deletions

View File

@ -10,8 +10,10 @@ go_library(
srcs = [
"conditions.go",
"create_resources.go",
"delete_resources.go",
"density_utils.go",
"deployment.go",
"paths.go",
"pod_store.go",
"replicaset.go",
"runners.go",
@ -21,6 +23,7 @@ go_library(
importpath = "k8s.io/kubernetes/test/utils",
deps = [
"//pkg/api/v1/pod:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/extensions:go_default_library",
@ -30,6 +33,7 @@ go_library(
"//pkg/util/labels:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/batch/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",

View File

@ -51,7 +51,16 @@ func RetryWithExponentialBackOff(fn wait.ConditionFunc) error {
}
func IsRetryableAPIError(err error) bool {
return apierrs.IsTimeout(err) || apierrs.IsServerTimeout(err) || apierrs.IsTooManyRequests(err) || utilnet.IsProbableEOF(err)
// These errors may indicate a transient error that we can retry in tests.
if apierrs.IsInternalError(err) || apierrs.IsTimeout(err) || apierrs.IsServerTimeout(err) ||
apierrs.IsTooManyRequests(err) || utilnet.IsProbableEOF(err) || utilnet.IsConnectionReset(err) {
return true
}
// If the error sends the Retry-After header, we respect it as an explicit confirmation we should retry.
if _, shouldRetry := apierrs.SuggestsClientDelay(err); shouldRetry {
return true
}
return false
}
func CreatePodWithRetries(c clientset.Interface, namespace string, obj *v1.Pod) error {

View File

@ -0,0 +1,71 @@
/*
Copyright 2018 The Kubernetes 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.
*/
// TODO: Refactor common part of functions in this file for generic object kinds.
package utils
import (
"fmt"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
clientset "k8s.io/client-go/kubernetes"
appsinternal "k8s.io/kubernetes/pkg/apis/apps"
batchinternal "k8s.io/kubernetes/pkg/apis/batch"
api "k8s.io/kubernetes/pkg/apis/core"
extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
)
func deleteResource(c clientset.Interface, kind schema.GroupKind, namespace, name string, options *metav1.DeleteOptions) error {
switch kind {
case api.Kind("Pod"):
return c.CoreV1().Pods(namespace).Delete(name, options)
case api.Kind("ReplicationController"):
return c.CoreV1().ReplicationControllers(namespace).Delete(name, options)
case extensionsinternal.Kind("ReplicaSet"), appsinternal.Kind("ReplicaSet"):
return c.ExtensionsV1beta1().ReplicaSets(namespace).Delete(name, options)
case extensionsinternal.Kind("Deployment"), appsinternal.Kind("Deployment"):
return c.ExtensionsV1beta1().Deployments(namespace).Delete(name, options)
case extensionsinternal.Kind("DaemonSet"):
return c.ExtensionsV1beta1().DaemonSets(namespace).Delete(name, options)
case batchinternal.Kind("Job"):
return c.BatchV1().Jobs(namespace).Delete(name, options)
case api.Kind("Secret"):
return c.CoreV1().Secrets(namespace).Delete(name, options)
case api.Kind("ConfigMap"):
return c.CoreV1().ConfigMaps(namespace).Delete(name, options)
case api.Kind("Service"):
return c.CoreV1().Services(namespace).Delete(name, options)
default:
return fmt.Errorf("Unsupported kind when deleting: %v", kind)
}
}
func DeleteResourceWithRetries(c clientset.Interface, kind schema.GroupKind, namespace, name string, options *metav1.DeleteOptions) error {
deleteFunc := func() (bool, error) {
err := deleteResource(c, kind, namespace, name, options)
if err == nil || apierrs.IsNotFound(err) {
return true, nil
}
if IsRetryableAPIError(err) {
return false, nil
}
return false, fmt.Errorf("Failed to delete object with non-retriable error: %v", err)
}
return RetryWithExponentialBackOff(deleteFunc)
}

View File

@ -22,8 +22,8 @@ import (
"github.com/davecgh/go-spew/spew"
apps "k8s.io/api/apps/v1"
"k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
clientset "k8s.io/client-go/kubernetes"
@ -34,7 +34,7 @@ import (
type LogfFn func(format string, args ...interface{})
func LogReplicaSetsOfDeployment(deployment *extensions.Deployment, allOldRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, logf LogfFn) {
func LogReplicaSetsOfDeployment(deployment *apps.Deployment, allOldRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, logf LogfFn) {
if newRS != nil {
logf(spew.Sprintf("New ReplicaSet %q of Deployment %q:\n%+v", newRS.Name, deployment.Name, *newRS))
} else {
@ -48,7 +48,7 @@ func LogReplicaSetsOfDeployment(deployment *extensions.Deployment, allOldRSs []*
}
}
func LogPodsOfDeployment(c clientset.Interface, deployment *extensions.Deployment, rsList []*extensions.ReplicaSet, logf LogfFn) {
func LogPodsOfDeployment(c clientset.Interface, deployment *apps.Deployment, rsList []*apps.ReplicaSet, logf LogfFn) {
minReadySeconds := deployment.Spec.MinReadySeconds
podListFunc := func(namespace string, options metav1.ListOptions) (*v1.PodList, error) {
return c.CoreV1().Pods(namespace).List(options)
@ -72,15 +72,15 @@ func LogPodsOfDeployment(c clientset.Interface, deployment *extensions.Deploymen
// If during a rolling update (rolling == true), returns an error if the deployment's
// rolling update strategy (max unavailable or max surge) is broken at any times.
// It's not seen as a rolling update if shortly after a scaling event or the deployment is just created.
func waitForDeploymentCompleteMaybeCheckRolling(c clientset.Interface, d *extensions.Deployment, rolling bool, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
func waitForDeploymentCompleteMaybeCheckRolling(c clientset.Interface, d *apps.Deployment, rolling bool, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
var (
deployment *extensions.Deployment
deployment *apps.Deployment
reason string
)
err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
var err error
deployment, err = c.ExtensionsV1beta1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{})
deployment, err = c.AppsV1().Deployments(d.Namespace).Get(d.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
@ -114,9 +114,9 @@ func waitForDeploymentCompleteMaybeCheckRolling(c clientset.Interface, d *extens
return nil
}
func checkRollingUpdateStatus(c clientset.Interface, deployment *extensions.Deployment, logf LogfFn) (string, error) {
func checkRollingUpdateStatus(c clientset.Interface, deployment *apps.Deployment, logf LogfFn) (string, error) {
var reason string
oldRSs, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.ExtensionsV1beta1())
oldRSs, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.AppsV1())
if err != nil {
return "", err
}
@ -128,7 +128,7 @@ func checkRollingUpdateStatus(c clientset.Interface, deployment *extensions.Depl
allRSs := append(oldRSs, newRS)
// The old/new ReplicaSets need to contain the pod-template-hash label
for i := range allRSs {
if !labelsutil.SelectorHasLabel(allRSs[i].Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) {
if !labelsutil.SelectorHasLabel(allRSs[i].Spec.Selector, apps.DefaultDeploymentUniqueLabelKey) {
reason = "all replica sets need to contain the pod-template-hash label"
return reason, nil
}
@ -153,7 +153,7 @@ func checkRollingUpdateStatus(c clientset.Interface, deployment *extensions.Depl
// Waits for the deployment to complete, and check rolling update strategy isn't broken at any times.
// Rolling update strategy should not be broken during a rolling update.
func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *extensions.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *apps.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
rolling := true
return waitForDeploymentCompleteMaybeCheckRolling(c, d, rolling, logf, pollInterval, pollTimeout)
}
@ -161,7 +161,7 @@ func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *extensio
// Waits for the deployment to complete, and don't check if rolling update strategy is broken.
// Rolling update strategy is used only during a rolling update, and can be violated in other situations,
// such as shortly after a scaling event or the deployment is just created.
func WaitForDeploymentComplete(c clientset.Interface, d *extensions.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
func WaitForDeploymentComplete(c clientset.Interface, d *apps.Deployment, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
rolling := false
return waitForDeploymentCompleteMaybeCheckRolling(c, d, rolling, logf, pollInterval, pollTimeout)
}
@ -169,17 +169,17 @@ func WaitForDeploymentComplete(c clientset.Interface, d *extensions.Deployment,
// WaitForDeploymentRevisionAndImage waits for the deployment's and its new RS's revision and container image to match the given revision and image.
// Note that deployment revision and its new RS revision should be updated shortly, so we only wait for 1 minute here to fail early.
func WaitForDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName string, revision, image string, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
var deployment *extensions.Deployment
var newRS *extensions.ReplicaSet
var deployment *apps.Deployment
var newRS *apps.ReplicaSet
var reason string
err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
var err error
deployment, err = c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
deployment, err = c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
if err != nil {
return false, err
}
// The new ReplicaSet needs to be non-nil and contain the pod-template-hash label
newRS, err = deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1())
newRS, err = deploymentutil.GetNewReplicaSet(deployment, c.AppsV1())
if err != nil {
return false, err
}
@ -205,26 +205,26 @@ func WaitForDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName
// CheckDeploymentRevisionAndImage checks if the input deployment's and its new replica set's revision and image are as expected.
func CheckDeploymentRevisionAndImage(c clientset.Interface, ns, deploymentName, revision, image string) error {
deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("unable to get deployment %s during revision check: %v", deploymentName, err)
}
// Check revision of the new replica set of this deployment
newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.ExtensionsV1beta1())
newRS, err := deploymentutil.GetNewReplicaSet(deployment, c.AppsV1())
if err != nil {
return fmt.Errorf("unable to get new replicaset of deployment %s during revision check: %v", deploymentName, err)
}
return checkRevisionAndImage(deployment, newRS, revision, image)
}
func checkRevisionAndImage(deployment *extensions.Deployment, newRS *extensions.ReplicaSet, revision, image string) error {
func checkRevisionAndImage(deployment *apps.Deployment, newRS *apps.ReplicaSet, revision, image string) error {
// The new ReplicaSet needs to be non-nil and contain the pod-template-hash label
if newRS == nil {
return fmt.Errorf("new replicaset for deployment %q is yet to be created", deployment.Name)
}
if !labelsutil.SelectorHasLabel(newRS.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) {
return fmt.Errorf("new replica set %q doesn't have %q label selector", newRS.Name, extensions.DefaultDeploymentUniqueLabelKey)
if !labelsutil.SelectorHasLabel(newRS.Spec.Selector, apps.DefaultDeploymentUniqueLabelKey) {
return fmt.Errorf("new replica set %q doesn't have %q label selector", newRS.Name, apps.DefaultDeploymentUniqueLabelKey)
}
// Check revision of this deployment, and of the new replica set of this deployment
if deployment.Annotations == nil || deployment.Annotations[deploymentutil.RevisionAnnotation] != revision {
@ -252,19 +252,19 @@ func containsImage(containers []v1.Container, imageName string) bool {
return false
}
type UpdateDeploymentFunc func(d *extensions.Deployment)
type UpdateDeploymentFunc func(d *apps.Deployment)
func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateDeploymentFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*extensions.Deployment, error) {
var deployment *extensions.Deployment
func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateDeploymentFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*apps.Deployment, error) {
var deployment *apps.Deployment
var updateErr error
pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
var err error
if deployment, err = c.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{}); err != nil {
if deployment, err = c.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{}); err != nil {
return false, err
}
// Apply the update, then attempt to push it to the apiserver.
applyUpdate(deployment)
if deployment, err = c.ExtensionsV1beta1().Deployments(namespace).Update(deployment); err == nil {
if deployment, err = c.AppsV1().Deployments(namespace).Update(deployment); err == nil {
logf("Updating deployment %s", name)
return true, nil
}
@ -278,20 +278,20 @@ func UpdateDeploymentWithRetries(c clientset.Interface, namespace, name string,
}
func WaitForObservedDeployment(c clientset.Interface, ns, deploymentName string, desiredGeneration int64) error {
return deploymentutil.WaitForObservedDeployment(func() (*extensions.Deployment, error) {
return c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
return deploymentutil.WaitForObservedDeployment(func() (*apps.Deployment, error) {
return c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
}, desiredGeneration, 2*time.Second, 1*time.Minute)
}
// WaitForDeploymentRollbackCleared waits for given deployment either started rolling back or doesn't need to rollback.
func WaitForDeploymentRollbackCleared(c clientset.Interface, ns, deploymentName string, pollInterval, pollTimeout time.Duration) error {
err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
deployment, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
deployment, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
if err != nil {
return false, err
}
// Rollback not set or is kicked off
if deployment.Spec.RollbackTo == nil {
if deployment.Annotations[apps.DeprecatedRollbackTo] == "" {
return true, nil
}
return false, nil
@ -304,9 +304,9 @@ func WaitForDeploymentRollbackCleared(c clientset.Interface, ns, deploymentName
// WaitForDeploymentUpdatedReplicasGTE waits for given deployment to be observed by the controller and has at least a number of updatedReplicas
func WaitForDeploymentUpdatedReplicasGTE(c clientset.Interface, ns, deploymentName string, minUpdatedReplicas int32, desiredGeneration int64, pollInterval, pollTimeout time.Duration) error {
var deployment *extensions.Deployment
var deployment *apps.Deployment
err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
d, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
d, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
if err != nil {
return false, err
}
@ -319,10 +319,10 @@ func WaitForDeploymentUpdatedReplicasGTE(c clientset.Interface, ns, deploymentNa
return nil
}
func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType extensions.DeploymentConditionType, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
var deployment *extensions.Deployment
func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType apps.DeploymentConditionType, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
var deployment *apps.Deployment
pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
d, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
d, err := c.AppsV1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
if err != nil {
return false, err
}
@ -332,7 +332,7 @@ func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, r
})
if pollErr == wait.ErrWaitTimeout {
pollErr = fmt.Errorf("deployment %q never updated with the desired condition and reason, latest deployment conditions: %+v", deployment.Name, deployment.Status.Conditions)
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.ExtensionsV1beta1())
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.AppsV1())
if err == nil {
LogReplicaSetsOfDeployment(deployment, allOldRSs, newRS, logf)
LogPodsOfDeployment(c, deployment, append(allOldRSs, newRS), logf)

View File

@ -48,7 +48,7 @@ func (i *ImageConfig) SetVersion(version string) {
}
var (
AdmissionWebhook = ImageConfig{e2eRegistry, "k8s-sample-admission-webhook", "1.9v1", true}
AdmissionWebhook = ImageConfig{e2eRegistry, "k8s-sample-admission-webhook", "1.10v2", true}
APIServer = ImageConfig{e2eRegistry, "k8s-aggregator-sample-apiserver", "1.7v2", true}
AppArmorLoader = ImageConfig{gcRegistry, "apparmor-loader", "0.1", false}
BusyBox = ImageConfig{gcRegistry, "busybox", "1.24", false}
@ -57,7 +57,7 @@ var (
CudaVectorAdd = ImageConfig{e2eRegistry, "cuda-vector-add", "1.0", true}
Dnsutils = ImageConfig{e2eRegistry, "dnsutils", "1.0", true}
DNSMasq = ImageConfig{gcRegistry, "k8s-dns-dnsmasq", "1.14.5", true}
EchoServer = ImageConfig{gcRegistry, "echoserver", "1.6", false}
EchoServer = ImageConfig{gcRegistry, "echoserver", "1.10", false}
EntrypointTester = ImageConfig{e2eRegistry, "entrypoint-tester", "1.0", true}
E2ENet = ImageConfig{gcRegistry, "e2e-net", "1.0", true}
Fakegitserver = ImageConfig{e2eRegistry, "fakegitserver", "1.0", true}
@ -84,7 +84,7 @@ var (
NoSnatTestProxy = ImageConfig{e2eRegistry, "no-snat-test-proxy", "1.0", true}
NWayHTTP = ImageConfig{e2eRegistry, "n-way-http", "1.0", true}
// When these values are updated, also update cmd/kubelet/app/options/container_runtime.go
Pause = ImageConfig{gcRegistry, "pause", "3.1", true}
Pause = ImageConfig{gcRegistry, "pause", "3.1", false}
Porter = ImageConfig{e2eRegistry, "porter", "1.0", true}
PortForwardTester = ImageConfig{e2eRegistry, "port-forward-tester", "1.0", true}
Redis = ImageConfig{e2eRegistry, "redis", "1.0", true}
@ -93,11 +93,10 @@ var (
SDDummyExporter = ImageConfig{gcRegistry, "sd-dummy-exporter", "v0.1.0", false}
ServeHostname = ImageConfig{e2eRegistry, "serve-hostname", "1.0", true}
TestWebserver = ImageConfig{e2eRegistry, "test-webserver", "1.0", true}
VolumeNFSServer = ImageConfig{gcRegistry, "volume-nfs", "0.8", false}
VolumeISCSIServer = ImageConfig{gcRegistry, "volume-icsci", "0.1", false}
VolumeGlusterServer = ImageConfig{gcRegistry, "volume-gluster", "0.2", false}
VolumeCephServer = ImageConfig{gcRegistry, "volume-ceph", "0.1", false}
VolumeRBDServer = ImageConfig{gcRegistry, "volume-rbd", "0.1", false}
VolumeNFSServer = ImageConfig{e2eRegistry, "volume-nfs", "0.8", false}
VolumeISCSIServer = ImageConfig{e2eRegistry, "volume-iscsi", "0.2", false}
VolumeGlusterServer = ImageConfig{e2eRegistry, "volume-gluster", "0.5", false}
VolumeRBDServer = ImageConfig{e2eRegistry, "volume-rbd", "0.2", false}
)
func GetE2EImage(image ImageConfig) string {
@ -113,7 +112,7 @@ func GetE2EImageWithArch(image ImageConfig, arch string) string {
}
}
// GetPauseImageNameForHostArch fetches the pause image name for the same architecture the test is running on.
func GetPauseImageNameForHostArch() string {
// GetPauseImageName returns the pause image name with proper version
func GetPauseImageName() string {
return GetE2EImage(Pause)
}

72
vendor/k8s.io/kubernetes/test/utils/paths.go generated vendored Normal file
View File

@ -0,0 +1,72 @@
/*
Copyright 2018 The Kubernetes 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 utils
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
)
// GetK8sRootDir returns the root directory for kubernetes, if present in the gopath.
func GetK8sRootDir() (string, error) {
dir, err := RootDir()
if err != nil {
return "", err
}
return filepath.Join(dir, fmt.Sprintf("%s/", "k8s.io/kubernetes")), nil
}
// GetCAdvisorRootDir returns the root directory for cAdvisor, if present in the gopath.
func GetCAdvisorRootDir() (string, error) {
dir, err := RootDir()
if err != nil {
return "", err
}
return filepath.Join(dir, fmt.Sprintf("%s/", "github.com/google/cadvisor")), nil
}
// RootDir gets the on-disk kubernetes source directory, returning an error is none is found
func RootDir() (string, error) {
// Get the directory of the current executable
_, testExec, _, _ := runtime.Caller(0)
path := filepath.Dir(testExec)
// Look for the kubernetes source root directory
if strings.Contains(path, "k8s.io/kubernetes") {
splitPath := strings.Split(path, "k8s.io/kubernetes")
return splitPath[0], nil
}
return "", errors.New("could not find kubernetes source root directory")
}
// GetK8sBuildOutputDir returns the build output directory for k8s
func GetK8sBuildOutputDir() (string, error) {
k8sRoot, err := GetK8sRootDir()
if err != nil {
return "", err
}
buildOutputDir := filepath.Join(k8sRoot, "_output/local/go/bin")
if _, err := os.Stat(buildOutputDir); err != nil {
return "", err
}
return buildOutputDir, nil
}

View File

@ -17,11 +17,14 @@ limitations under the License.
package utils
import (
"time"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
@ -34,7 +37,7 @@ type PodStore struct {
Reflector *cache.Reflector
}
func NewPodStore(c clientset.Interface, namespace string, label labels.Selector, field fields.Selector) *PodStore {
func NewPodStore(c clientset.Interface, namespace string, label labels.Selector, field fields.Selector) (*PodStore, error) {
lw := &cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
options.LabelSelector = label.String()
@ -52,7 +55,15 @@ func NewPodStore(c clientset.Interface, namespace string, label labels.Selector,
stopCh := make(chan struct{})
reflector := cache.NewReflector(lw, &v1.Pod{}, store, 0)
go reflector.Run(stopCh)
return &PodStore{Store: store, stopCh: stopCh, Reflector: reflector}
if err := wait.PollImmediate(50*time.Millisecond, 2*time.Minute, func() (bool, error) {
if len(reflector.LastSyncResourceVersion()) != 0 {
return true, nil
}
return false, nil
}); err != nil {
return nil, err
}
return &PodStore{Store: store, stopCh: stopCh, Reflector: reflector}, nil
}
func (s *PodStore) List() []*v1.Pod {

View File

@ -21,25 +21,25 @@ import (
"testing"
"time"
extensions "k8s.io/api/extensions/v1beta1"
apps "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
clientset "k8s.io/client-go/kubernetes"
)
type UpdateReplicaSetFunc func(d *extensions.ReplicaSet)
type UpdateReplicaSetFunc func(d *apps.ReplicaSet)
func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*extensions.ReplicaSet, error) {
var rs *extensions.ReplicaSet
func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*apps.ReplicaSet, error) {
var rs *apps.ReplicaSet
var updateErr error
pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
var err error
if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil {
if rs, err = c.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil {
return false, err
}
// Apply the update, then attempt to push it to the apiserver.
applyUpdate(rs)
if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Update(rs); err == nil {
if rs, err = c.AppsV1().ReplicaSets(namespace).Update(rs); err == nil {
logf("Updating replica set %q", name)
return true, nil
}
@ -53,10 +53,10 @@ func UpdateReplicaSetWithRetries(c clientset.Interface, namespace, name string,
}
// Verify .Status.Replicas is equal to .Spec.Replicas
func WaitRSStable(t *testing.T, clientSet clientset.Interface, rs *extensions.ReplicaSet, pollInterval, pollTimeout time.Duration) error {
func WaitRSStable(t *testing.T, clientSet clientset.Interface, rs *apps.ReplicaSet, pollInterval, pollTimeout time.Duration) error {
desiredGeneration := rs.Generation
if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
newRS, err := clientSet.ExtensionsV1beta1().ReplicaSets(rs.Namespace).Get(rs.Name, metav1.GetOptions{})
newRS, err := clientSet.AppsV1().ReplicaSets(rs.Namespace).Get(rs.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
@ -67,17 +67,17 @@ func WaitRSStable(t *testing.T, clientSet clientset.Interface, rs *extensions.Re
return nil
}
func UpdateReplicaSetStatusWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*extensions.ReplicaSet, error) {
var rs *extensions.ReplicaSet
func UpdateReplicaSetStatusWithRetries(c clientset.Interface, namespace, name string, applyUpdate UpdateReplicaSetFunc, logf LogfFn, pollInterval, pollTimeout time.Duration) (*apps.ReplicaSet, error) {
var rs *apps.ReplicaSet
var updateErr error
pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
var err error
if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil {
if rs, err = c.AppsV1().ReplicaSets(namespace).Get(name, metav1.GetOptions{}); err != nil {
return false, err
}
// Apply the update, then attempt to push it to the apiserver.
applyUpdate(rs)
if rs, err = c.ExtensionsV1beta1().ReplicaSets(namespace).UpdateStatus(rs); err == nil {
if rs, err = c.AppsV1().ReplicaSets(namespace).UpdateStatus(rs); err == nil {
logf("Updating replica set %q", name)
return true, nil
}

View File

@ -124,6 +124,7 @@ type RCConfig struct {
CpuLimit int64 // millicores
MemRequest int64 // bytes
MemLimit int64 // bytes
GpuLimit int64 // count
ReadinessProbe *v1.Probe
DNSPolicy *v1.DNSPolicy
PriorityClassName string
@ -131,8 +132,9 @@ type RCConfig struct {
// Env vars, set the same for every pod.
Env map[string]string
// Extra labels added to every pod.
Labels map[string]string
// Extra labels and annotations added to every pod.
Labels map[string]string
Annotations map[string]string
// Node selector for pods in the RC.
NodeSelector map[string]string
@ -292,7 +294,8 @@ func (config *DeploymentConfig) create() error {
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"name": config.Name},
Labels: map[string]string{"name": config.Name},
Annotations: config.Annotations,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
@ -362,7 +365,8 @@ func (config *ReplicaSetConfig) create() error {
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"name": config.Name},
Labels: map[string]string{"name": config.Name},
Annotations: config.Annotations,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
@ -428,7 +432,8 @@ func (config *JobConfig) create() error {
Completions: func(i int) *int32 { x := int32(i); return &x }(config.Replicas),
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"name": config.Name},
Labels: map[string]string{"name": config.Name},
Annotations: config.Annotations,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
@ -542,7 +547,8 @@ func (config *RCConfig) create() error {
},
Template: &v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"name": config.Name},
Labels: map[string]string{"name": config.Name},
Annotations: config.Annotations,
},
Spec: v1.PodSpec{
Affinity: config.Affinity,
@ -610,7 +616,7 @@ func (config *RCConfig) applyTo(template *v1.PodTemplateSpec) {
c.Ports = append(c.Ports, v1.ContainerPort{Name: k, ContainerPort: int32(v), HostPort: int32(v)})
}
}
if config.CpuLimit > 0 || config.MemLimit > 0 {
if config.CpuLimit > 0 || config.MemLimit > 0 || config.GpuLimit > 0 {
template.Spec.Containers[0].Resources.Limits = v1.ResourceList{}
}
if config.CpuLimit > 0 {
@ -628,6 +634,9 @@ func (config *RCConfig) applyTo(template *v1.PodTemplateSpec) {
if config.MemRequest > 0 {
template.Spec.Containers[0].Resources.Requests[v1.ResourceMemory] = *resource.NewQuantity(config.MemRequest, resource.DecimalSI)
}
if config.GpuLimit > 0 {
template.Spec.Containers[0].Resources.Limits["nvidia.com/gpu"] = *resource.NewQuantity(config.GpuLimit, resource.DecimalSI)
}
if len(config.Volumes) > 0 {
template.Spec.Volumes = config.Volumes
}
@ -646,6 +655,7 @@ type RCStartupStatus struct {
RunningButNotReady int
Waiting int
Pending int
Scheduled int
Unknown int
Inactive int
FailedContainers int
@ -699,6 +709,10 @@ func ComputeRCStartupStatus(pods []*v1.Pod, expected int) RCStartupStatus {
} else if p.Status.Phase == v1.PodUnknown {
startupStatus.Unknown++
}
// Record count of scheduled pods (useful for computing scheduler throughput).
if p.Spec.NodeName != "" {
startupStatus.Scheduled++
}
}
return startupStatus
}
@ -714,8 +728,11 @@ func (config *RCConfig) start() error {
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": config.Name}))
PodStore := NewPodStore(config.Client, config.Namespace, label, fields.Everything())
defer PodStore.Stop()
ps, err := NewPodStore(config.Client, config.Namespace, label, fields.Everything())
if err != nil {
return err
}
defer ps.Stop()
interval := config.PollInterval
if interval <= 0 {
@ -731,7 +748,7 @@ func (config *RCConfig) start() error {
for oldRunning != config.Replicas {
time.Sleep(interval)
pods := PodStore.List()
pods := ps.List()
startupStatus := ComputeRCStartupStatus(pods, config.Replicas)
pods = startupStatus.Created
@ -828,20 +845,33 @@ func StartPods(c clientset.Interface, replicas int, namespace string, podNamePre
// Wait up to 10 minutes for all matching pods to become Running and at least one
// matching pod exists.
func WaitForPodsWithLabelRunning(c clientset.Interface, ns string, label labels.Selector) error {
return WaitForEnoughPodsWithLabelRunning(c, ns, label, -1)
}
// Wait up to 10 minutes for at least 'replicas' many pods to be Running and at least
// one matching pod exists. If 'replicas' is < 0, wait for all matching pods running.
func WaitForEnoughPodsWithLabelRunning(c clientset.Interface, ns string, label labels.Selector, replicas int) error {
running := false
PodStore := NewPodStore(c, ns, label, fields.Everything())
defer PodStore.Stop()
waitLoop:
ps, err := NewPodStore(c, ns, label, fields.Everything())
if err != nil {
return err
}
defer ps.Stop()
for start := time.Now(); time.Since(start) < 10*time.Minute; time.Sleep(5 * time.Second) {
pods := PodStore.List()
pods := ps.List()
if len(pods) == 0 {
continue waitLoop
continue
}
runningPodsCount := 0
for _, p := range pods {
if p.Status.Phase != v1.PodRunning {
continue waitLoop
if p.Status.Phase == v1.PodRunning {
runningPodsCount++
}
}
if (replicas < 0 && runningPodsCount < len(pods)) || (runningPodsCount < replicas) {
continue
}
running = true
break
}
@ -1113,7 +1143,7 @@ func (config *SecretConfig) Run() error {
}
func (config *SecretConfig) Stop() error {
if err := config.Client.CoreV1().Secrets(config.Namespace).Delete(config.Name, &metav1.DeleteOptions{}); err != nil {
if err := DeleteResourceWithRetries(config.Client, api.Kind("Secret"), config.Namespace, config.Name, &metav1.DeleteOptions{}); err != nil {
return fmt.Errorf("Error deleting secret: %v", err)
}
config.LogFunc("Deleted secret %v/%v", config.Namespace, config.Name)
@ -1171,7 +1201,7 @@ func (config *ConfigMapConfig) Run() error {
}
func (config *ConfigMapConfig) Stop() error {
if err := config.Client.CoreV1().ConfigMaps(config.Namespace).Delete(config.Name, &metav1.DeleteOptions{}); err != nil {
if err := DeleteResourceWithRetries(config.Client, api.Kind("ConfigMap"), config.Namespace, config.Name, &metav1.DeleteOptions{}); err != nil {
return fmt.Errorf("Error deleting configmap: %v", err)
}
config.LogFunc("Deleted configmap %v/%v", config.Namespace, config.Name)
@ -1263,11 +1293,14 @@ func (config *DaemonConfig) Run() error {
timeout = 5 * time.Minute
}
podStore := NewPodStore(config.Client, config.Namespace, labels.SelectorFromSet(nameLabel), fields.Everything())
defer podStore.Stop()
ps, err := NewPodStore(config.Client, config.Namespace, labels.SelectorFromSet(nameLabel), fields.Everything())
if err != nil {
return err
}
defer ps.Stop()
err = wait.Poll(time.Second, timeout, func() (bool, error) {
pods := podStore.List()
pods := ps.List()
nodeHasDaemon := sets.NewString()
for _, pod := range pods {

View File

@ -20,6 +20,9 @@ import (
"fmt"
"time"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/scale"
"k8s.io/kubernetes/pkg/kubectl"
)
@ -29,13 +32,32 @@ const (
updateRetryInterval = 5 * time.Second
updateRetryTimeout = 1 * time.Minute
waitRetryInterval = 5 * time.Second
waitRetryTImeout = 5 * time.Minute
waitRetryTimeout = 5 * time.Minute
)
func ScaleResourceWithRetries(scaler kubectl.Scaler, namespace, name string, size uint) error {
waitForScale := kubectl.NewRetryParams(updateRetryInterval, updateRetryTimeout)
waitForReplicas := kubectl.NewRetryParams(waitRetryInterval, waitRetryTImeout)
if err := scaler.Scale(namespace, name, size, nil, waitForScale, waitForReplicas); err != nil {
func RetryErrorCondition(condition wait.ConditionFunc) wait.ConditionFunc {
return func() (bool, error) {
done, err := condition()
if err != nil && IsRetryableAPIError(err) {
return false, nil
}
return done, err
}
}
func ScaleResourceWithRetries(scalesGetter scale.ScalesGetter, namespace, name string, size uint, gr schema.GroupResource) error {
scaler := kubectl.NewScaler(scalesGetter)
preconditions := &kubectl.ScalePrecondition{
Size: -1,
ResourceVersion: "",
}
waitForReplicas := kubectl.NewRetryParams(waitRetryInterval, waitRetryTimeout)
cond := RetryErrorCondition(kubectl.ScaleCondition(scaler, preconditions, namespace, name, size, nil, gr))
err := wait.PollImmediate(updateRetryInterval, updateRetryTimeout, cond)
if err == nil {
err = kubectl.WaitForScaleHasDesiredReplicas(scalesGetter, gr, name, namespace, size, waitForReplicas)
}
if err != nil {
return fmt.Errorf("Error while scaling %s to %d replicas: %v", name, size, err)
}
return nil