batchinternal "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/test/e2e/framework" jobutil "k8s.io/kubernetes/test/e2e/framework/job" <ins> e2enode "k8s.io/kubernetes/test/e2e/framework/node" </ins> e2epod "k8s.io/kubernetes/test/e2e/framework/pod" "github.com/onsi/ginkgo"


framework.ConformanceIt("should run a job to completion when tasks sometimes fail and are locally restarted", func() { ginkgo.By("Creating a job") // One failure, then a success, local restarts. <del> // We can't use the random failure approach used by the // non-local test below, because kubelet will throttle // frequently failing containers in a given pod, ramping // up to 5 minutes between restarts, making test timeouts // due to successive failures too likely with a reasonable // test timeout. </del> <ins> // We can't use the random failure approach, because kubelet will // throttle frequently failing containers in a given pod, ramping // up to 5 minutes between restarts, making test timeout due to // successive failures too likely with a reasonable test timeout. </ins> job := jobutil.NewTestJob("failOnce", "fail-once-local", v1.RestartPolicyOnFailure, parallelism, completions, nil, backoffLimit) job, err := jobutil.CreateJob(f.ClientSet, f.Namespace.Name, job) framework.ExpectNoError(err, "failed to create job in namespace: %s", f.Namespace.Name)


// Pods sometimes fail, but eventually succeed, after pod restarts ginkgo.It("should run a job to completion when tasks sometimes fail and are not locally restarted", func() { <ins> // One failure, then a success, no local restarts. // We can't use the random failure approach, because JobController // will throttle frequently failing Pods of a given Job, ramping // up to 6 minutes between restarts, making test timeout due to // successive failures. // Instead, we force the Job's Pods to be scheduled to a single Node // and use a hostPath volume to persist data across new Pods. ginkgo.By("Looking for a node to schedule job pod") node, err := e2enode.GetRandomReadySchedulableNode(f.ClientSet) framework.ExpectNoError(err) </ins> ginkgo.By("Creating a job") <del> // 50% chance of container success, local restarts. // Can't use the failOnce approach because that relies // on an emptyDir, which is not preserved across new pods. // Worst case analysis: 15 failures, each taking 1 minute to // run due to some slowness, 1 in 2^15 chance of happening, // causing test flake.  Should be very rare. // With the introduction of backoff limit and high failure rate this // is hitting its timeout, the 3 is a reasonable that should make this // test less flaky, for now. job := jobutil.NewTestJob("randomlySucceedOrFail", "rand-non-local", v1.RestartPolicyNever, parallelism, 3, nil, 999) job, err := jobutil.CreateJob(f.ClientSet, f.Namespace.Name, job) </del> <ins> job := jobutil.NewTestJobOnNode("failOnce", "fail-once-non-local", v1.RestartPolicyNever, parallelism, completions, nil, backoffLimit, node.Name) job, err = jobutil.CreateJob(f.ClientSet, f.Namespace.Name, job) </ins> framework.ExpectNoError(err, "failed to create job in namespace: %s", f.Namespace.Name) ginkgo.By("Ensuring job reaches completions")


"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", <ins> "//staging/src/k8s.io/apimachinery/pkg/util/rand:go_default_library", </ins> "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//test/e2e/framework:go_default_library",


batchv1 "k8s.io/api/batch/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" <ins> "k8s.io/apimachinery/pkg/util/rand" </ins> "k8s.io/kubernetes/test/e2e/framework" )


// policy of the containers in which the Pod is running. Parallelism is the Job's parallelism, and completions is the // Job's required number of completions. func NewTestJob(behavior, name string, rPol v1.RestartPolicy, parallelism, completions int32, activeDeadlineSeconds *int64, backoffLimit int32) *batchv1.Job { <ins> anyNode := "" return NewTestJobOnNode(behavior, name, rPol, parallelism, completions, activeDeadlineSeconds, backoffLimit, anyNode) } // NewTestJobOnNode is similar to NewTestJob but supports specifying a Node on which the Job's Pods will run. // Empty nodeName means no node selection constraints. func NewTestJobOnNode(behavior, name string, rPol v1.RestartPolicy, parallelism, completions int32, activeDeadlineSeconds *int64, backoffLimit int32, nodeName string) *batchv1.Job { </ins> manualSelector := false job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{


SecurityContext: &v1.SecurityContext{}, }, }, <ins> NodeName: nodeName, </ins> }, }, },


job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "exit $(( $RANDOM / 16384 ))"} case "failOnce": // Fail the first the container of the pod is run, and <del> // succeed the second time. Checks for file on emptydir. </del> <ins> // succeed the second time. Checks for file on a data volume. </ins> // If present, succeed.  If not, create but fail. <del> // Note that this cannot be used with RestartNever because // it always fails the first time for a pod. </del> <ins> // If RestartPolicy is Never, the nodeName should be set to // ensure all job pods run on a single node and the volume // will be mounted from a hostPath instead. if len(nodeName) > 0 { randomDir := "/tmp/job-e2e/" + rand.String(10) hostPathType := v1.HostPathDirectoryOrCreate job.Spec.Template.Spec.Volumes[0].VolumeSource = v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: randomDir, Type: &hostPathType}} // Tests involving r/w operations on hostPath volume needs to run in // privileged mode for SELinux enabled distro, while Windows platform // neither supports nor needs privileged mode. privileged := !framework.NodeOSDistroIs("windows") job.Spec.Template.Spec.Containers[0].SecurityContext.Privileged = &privileged } </ins> job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "if [[ -r /data/foo ]] ; then exit 0 ; else touch /data/foo ; exit 1 ; fi"} } return job


package common import ( <ins> "encoding/json" </ins> "fmt" "k8s.io/api/core/v1"


"k8s.io/kubernetes/test/e2e/framework" imageutils "k8s.io/kubernetes/test/utils/image" <ins> "encoding/base64" </ins> "github.com/onsi/ginkgo" <ins> "k8s.io/apimachinery/pkg/types" </ins> ) var _ = ginkgo.Describe("[sig-api-machinery] Secrets", func() {


secret, err := createEmptyKeySecretForTest(f) framework.ExpectError(err, "created secret %q with empty key in namespace %q", secret.Name, f.Namespace.Name) }) <ins> ginkgo.It("should patch a secret", func() { ginkgo.By("creating a secret") secretTestName := "test-secret-" + string(uuid.NewUUID()) // create a secret in the test namespace _, err := f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(&v1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: secretTestName, Labels: map[string]string{ "testsecret-constant": "true", }, }, Data: map[string][]byte{ "key": []byte("value"), }, Type: "Opaque", }) framework.ExpectNoError(err, "failed to create secret") ginkgo.By("listing secrets in all namespaces to ensure that there are more than zero") // list all secrets in all namespaces to ensure endpoint coverage secretsList, err := f.ClientSet.CoreV1().Secrets("").List(metav1.ListOptions{ LabelSelector: "testsecret-constant=true", }) framework.ExpectNoError(err, "failed to list secrets") framework.ExpectNotEqual(len(secretsList.Items), 0, "no secrets found") foundCreatedSecret := false var secretCreatedName string for _, val := range secretsList.Items { if val.ObjectMeta.Name == secretTestName && val.ObjectMeta.Namespace == f.Namespace.Name { foundCreatedSecret = true secretCreatedName = val.ObjectMeta.Name break } } framework.ExpectEqual(foundCreatedSecret, true, "unable to find secret by its value") ginkgo.By("patching the secret") // patch the secret in the test namespace secretPatchNewData := base64.StdEncoding.EncodeToString([]byte("value1")) secretPatch, err := json.Marshal(map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]string{"testsecret": "true"}, }, "data": map[string][]byte{"key": []byte(secretPatchNewData)}, }) framework.ExpectNoError(err, "failed to marshal JSON") _, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Patch(secretCreatedName, types.StrategicMergePatchType, []byte(secretPatch)) framework.ExpectNoError(err, "failed to patch secret") secret, err := f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Get(secretCreatedName, metav1.GetOptions{}) framework.ExpectNoError(err, "failed to get secret") secretDecodedstring, err := base64.StdEncoding.DecodeString(string(secret.Data["key"])) framework.ExpectNoError(err, "failed to decode secret from Base64") framework.ExpectEqual(string(secretDecodedstring), "value1", "found secret, but the data wasn't updated from the patch") ginkgo.By("deleting the secret using a LabelSelector") err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).DeleteCollection(&metav1.DeleteOptions{}, metav1.ListOptions{ LabelSelector: "testsecret=true", }) framework.ExpectNoError(err, "failed to delete patched secret") ginkgo.By("listing secrets in all namespaces, searching for label name and value in patch") // list all secrets in all namespaces secretsList, err = f.ClientSet.CoreV1().Secrets("").List(metav1.ListOptions{ LabelSelector: "testsecret-constant=true", }) framework.ExpectNoError(err, "failed to list secrets") foundCreatedSecret = false for _, val := range secretsList.Items { if val.ObjectMeta.Name == secretTestName && val.ObjectMeta.Namespace == f.Namespace.Name { foundCreatedSecret = true break } } framework.ExpectEqual(foundCreatedSecret, false, "secret was not deleted successfully") }) </ins> }) func newEnvFromSecret(namespace, name string) *v1.Secret {


test/e2e/common/secrets.go: "should be consumable from pods in env vars" test/e2e/common/secrets.go: "should be consumable via the environment" test/e2e/common/secrets.go: "should fail to create secret due to empty secret key" <ins> test/e2e/common/secrets.go: "should patch a secret" </ins> test/e2e/common/secrets_volume.go: "should be consumable from pods in volume" test/e2e/common/secrets_volume.go: "should be consumable from pods in volume with defaultMode set" test/e2e/common/secrets_volume.go: "should be consumable from pods in volume as non-root with defaultMode and fsGroup set"


framework.ExpectError(err, "created secret %q with empty key in namespace %q", secret.Name, f.Namespace.Name) }) <del> ginkgo.It("should patch a secret", func() { </del> <ins> /* Release : v1.18 Testname: Secret patching Description: A Secret is created. Listing all Secrets MUST return an empty list. Given the patching and fetching of the Secret, the fields MUST equal the new values. The Secret is deleted by it's static Label. Secrets are listed finally, the list MUST NOT include the originally created Secret. */ framework.ConformanceIt("should patch a secret", func() { </ins> ginkgo.By("creating a secret") secretTestName := "test-secret-" + string(uuid.NewUUID())


// The failure information is given by the error. type FitPredicate func(pod *v1.Pod, meta Metadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) <del> func isVolumeConflict(volume v1.Volume, pod *v1.Pod) bool { // fast path if there is no conflict checking targets. if volume.GCEPersistentDisk == nil && volume.AWSElasticBlockStore == nil && volume.RBD == nil && volume.ISCSI == nil { return false } for _, existingVolume := range pod.Spec.Volumes { // Same GCE disk mounted by multiple pods conflicts unless all pods mount it read-only. if volume.GCEPersistentDisk != nil && existingVolume.GCEPersistentDisk != nil { disk, existingDisk := volume.GCEPersistentDisk, existingVolume.GCEPersistentDisk if disk.PDName == existingDisk.PDName && !(disk.ReadOnly && existingDisk.ReadOnly) { return true } } if volume.AWSElasticBlockStore != nil && existingVolume.AWSElasticBlockStore != nil { if volume.AWSElasticBlockStore.VolumeID == existingVolume.AWSElasticBlockStore.VolumeID { return true } } if volume.ISCSI != nil && existingVolume.ISCSI != nil { iqn := volume.ISCSI.IQN eiqn := existingVolume.ISCSI.IQN // two ISCSI volumes are same, if they share the same iqn. As iscsi volumes are of type // RWO or ROX, we could permit only one RW mount. Same iscsi volume mounted by multiple Pods // conflict unless all other pods mount as read only. if iqn == eiqn && !(volume.ISCSI.ReadOnly && existingVolume.ISCSI.ReadOnly) { return true } } if volume.RBD != nil && existingVolume.RBD != nil { mon, pool, image := volume.RBD.CephMonitors, volume.RBD.RBDPool, volume.RBD.RBDImage emon, epool, eimage := existingVolume.RBD.CephMonitors, existingVolume.RBD.RBDPool, existingVolume.RBD.RBDImage // two RBDs images are the same if they share the same Ceph monitor, are in the same RADOS Pool, and have the same image name // only one read-write mount is permitted for the same RBD image. // same RBD image mounted by multiple Pods conflicts unless all Pods mount the image read-only if haveOverlap(mon, emon) && pool == epool && image == eimage && !(volume.RBD.ReadOnly && existingVolume.RBD.ReadOnly) { return true } } } return false } // NoDiskConflict evaluates if a pod can fit due to the volumes it requests, and those that // are already mounted. If there is already a volume mounted on that node, another pod that uses the same volume // can't be scheduled there. // This is GCE, Amazon EBS, ISCSI and Ceph RBD specific for now: // - GCE PD allows multiple mounts as long as they're all read-only // - AWS EBS forbids any two pods mounting the same volume ID // - Ceph RBD forbids if any two pods share at least same monitor, and match pool and image, and the image is read-only // - ISCSI forbids if any two pods share at least same IQN and ISCSI volume is read-only // TODO: migrate this into some per-volume specific code? func NoDiskConflict(pod *v1.Pod, meta Metadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { for _, v := range pod.Spec.Volumes { for _, ev := range nodeInfo.Pods() { if isVolumeConflict(v, ev) { return false, []PredicateFailureReason{ErrDiskConflict}, nil } } } return true, nil, nil } </del> // MaxPDVolumeCountChecker contains information to check the max number of volumes for a predicate. type MaxPDVolumeCountChecker struct { filter         VolumeFilter


return true, nil, nil } <del> // haveOverlap searches two arrays and returns true if they have at least one common element; returns false otherwise. func haveOverlap(a1, a2 []string) bool { if len(a1) > len(a2) { a1, a2 = a2, a1 } m := map[string]bool{} for _, val := range a1 { m[val] = true } for _, val := range a2 { if _, ok := m[val]; ok { return true } } return false } </del> // GeneralPredicates checks a group of predicates that the kubelet cares about. // DEPRECATED: this exist only because kubelet uses it. We should change kubelet to execute the individual predicates it requires. func GeneralPredicates(pod *v1.Pod, meta Metadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) {


} } <del> func TestGCEDiskConflicts(t *testing.T) { volState := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ PDName: "foo", }, }, }, }, } volState2 := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ PDName: "bar", }, }, }, }, } tests := []struct { pod      *v1.Pod nodeInfo *schedulernodeinfo.NodeInfo isOk     bool name     string }{ {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { ok, reasons, err := NoDiskConflict(test.pod, nil, test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } if !ok && !reflect.DeepEqual(reasons, expectedFailureReasons) { t.Errorf("unexpected failure reasons: %v, want: %v", reasons, expectedFailureReasons) } if test.isOk && !ok { t.Errorf("expected ok, got none.  %v %s", test.pod, test.nodeInfo) } if !test.isOk && ok { t.Errorf("expected no ok, got one.  %v %s", test.pod, test.nodeInfo) } }) } } func TestAWSDiskConflicts(t *testing.T) { volState := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{ VolumeID: "foo", }, }, }, }, } volState2 := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{ VolumeID: "bar", }, }, }, }, } tests := []struct { pod      *v1.Pod nodeInfo *schedulernodeinfo.NodeInfo isOk     bool name     string }{ {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { ok, reasons, err := NoDiskConflict(test.pod, nil, test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } if !ok && !reflect.DeepEqual(reasons, expectedFailureReasons) { t.Errorf("unexpected failure reasons: %v, want: %v", reasons, expectedFailureReasons) } if test.isOk && !ok { t.Errorf("expected ok, got none.  %v %s", test.pod, test.nodeInfo) } if !test.isOk && ok { t.Errorf("expected no ok, got one.  %v %s", test.pod, test.nodeInfo) } }) } } func TestRBDDiskConflicts(t *testing.T) { volState := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ RBD: &v1.RBDVolumeSource{ CephMonitors: []string{"a", "b"}, RBDPool:      "foo", RBDImage:     "bar", FSType:       "ext4", }, }, }, }, } volState2 := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ RBD: &v1.RBDVolumeSource{ CephMonitors: []string{"c", "d"}, RBDPool:      "foo", RBDImage:     "bar", FSType:       "ext4", }, }, }, }, } tests := []struct { pod      *v1.Pod nodeInfo *schedulernodeinfo.NodeInfo isOk     bool name     string }{ {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { ok, reasons, err := NoDiskConflict(test.pod, nil, test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } if !ok && !reflect.DeepEqual(reasons, expectedFailureReasons) { t.Errorf("unexpected failure reasons: %v, want: %v", reasons, expectedFailureReasons) } if test.isOk && !ok { t.Errorf("expected ok, got none.  %v %s", test.pod, test.nodeInfo) } if !test.isOk && ok { t.Errorf("expected no ok, got one.  %v %s", test.pod, test.nodeInfo) } }) } } func TestISCSIDiskConflicts(t *testing.T) { volState := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ ISCSI: &v1.ISCSIVolumeSource{ TargetPortal: "127.0.0.1:3260", IQN:          "iqn.2016-12.server:storage.target01", FSType:       "ext4", Lun:          0, }, }, }, }, } volState2 := v1.PodSpec{ Volumes: []v1.Volume{ { VolumeSource: v1.VolumeSource{ ISCSI: &v1.ISCSIVolumeSource{ TargetPortal: "127.0.0.1:3260", IQN:          "iqn.2017-12.server:storage.target01", FSType:       "ext4", Lun:          0, }, }, }, }, } tests := []struct { pod      *v1.Pod nodeInfo *schedulernodeinfo.NodeInfo isOk     bool name     string }{ {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { ok, reasons, err := NoDiskConflict(test.pod, nil, test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } if !ok && !reflect.DeepEqual(reasons, expectedFailureReasons) { t.Errorf("unexpected failure reasons: %v, want: %v", reasons, expectedFailureReasons) } if test.isOk && !ok { t.Errorf("expected ok, got none.  %v %s", test.pod, test.nodeInfo) } if !test.isOk && ok { t.Errorf("expected no ok, got one.  %v %s", test.pod, test.nodeInfo) } }) } } </del> // TODO: Add test case for RequiredDuringSchedulingRequiredDuringExecution after it's implemented. func TestPodFitsSelector(t *testing.T) { tests := []struct {


) // Fit is determined by non-conflicting disk volumes. <del> scheduler.RegisterFitPredicate(predicates.NoDiskConflictPred, predicates.NoDiskConflict) </del> <ins> scheduler.RegisterFitPredicateFactory( predicates.NoDiskConflictPred, func(args scheduler.AlgorithmFactoryArgs) predicates.FitPredicate { return nil }, ) </ins> // GeneralPredicates are the predicates that are enforced by all Kubernetes components // (e.g. kubelet and all schedulers)


visibility = ["//visibility:public"], deps = [ "//pkg/scheduler/algorithm/predicates:go_default_library", <del> "//pkg/scheduler/framework/plugins/migration:go_default_library", </del> "//pkg/scheduler/framework/v1alpha1:go_default_library", "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",


v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" <del> "k8s.io/kubernetes/pkg/scheduler/framework/plugins/migration" </del> framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" "k8s.io/kubernetes/pkg/scheduler/nodeinfo" )


return Name } <ins> func isVolumeConflict(volume v1.Volume, pod *v1.Pod) bool { // fast path if there is no conflict checking targets. if volume.GCEPersistentDisk == nil && volume.AWSElasticBlockStore == nil && volume.RBD == nil && volume.ISCSI == nil { return false } for _, existingVolume := range pod.Spec.Volumes { // Same GCE disk mounted by multiple pods conflicts unless all pods mount it read-only. if volume.GCEPersistentDisk != nil && existingVolume.GCEPersistentDisk != nil { disk, existingDisk := volume.GCEPersistentDisk, existingVolume.GCEPersistentDisk if disk.PDName == existingDisk.PDName && !(disk.ReadOnly && existingDisk.ReadOnly) { return true } } if volume.AWSElasticBlockStore != nil && existingVolume.AWSElasticBlockStore != nil { if volume.AWSElasticBlockStore.VolumeID == existingVolume.AWSElasticBlockStore.VolumeID { return true } } if volume.ISCSI != nil && existingVolume.ISCSI != nil { iqn := volume.ISCSI.IQN eiqn := existingVolume.ISCSI.IQN // two ISCSI volumes are same, if they share the same iqn. As iscsi volumes are of type // RWO or ROX, we could permit only one RW mount. Same iscsi volume mounted by multiple Pods // conflict unless all other pods mount as read only. if iqn == eiqn && !(volume.ISCSI.ReadOnly && existingVolume.ISCSI.ReadOnly) { return true } } if volume.RBD != nil && existingVolume.RBD != nil { mon, pool, image := volume.RBD.CephMonitors, volume.RBD.RBDPool, volume.RBD.RBDImage emon, epool, eimage := existingVolume.RBD.CephMonitors, existingVolume.RBD.RBDPool, existingVolume.RBD.RBDImage // two RBDs images are the same if they share the same Ceph monitor, are in the same RADOS Pool, and have the same image name // only one read-write mount is permitted for the same RBD image. // same RBD image mounted by multiple Pods conflicts unless all Pods mount the image read-only if haveOverlap(mon, emon) && pool == epool && image == eimage && !(volume.RBD.ReadOnly && existingVolume.RBD.ReadOnly) { return true } } } return false } // haveOverlap searches two arrays and returns true if they have at least one common element; returns false otherwise. func haveOverlap(a1, a2 []string) bool { if len(a1) > len(a2) { a1, a2 = a2, a1 } m := map[string]bool{} for _, val := range a1 { m[val] = true } for _, val := range a2 { if _, ok := m[val]; ok { return true } } return false } </ins> // Filter invoked at the filter extension point. <ins> // It evaluates if a pod can fit due to the volumes it requests, and those that // are already mounted. If there is already a volume mounted on that node, another pod that uses the same volume // can't be scheduled there. // This is GCE, Amazon EBS, ISCSI and Ceph RBD specific for now: // - GCE PD allows multiple mounts as long as they're all read-only // - AWS EBS forbids any two pods mounting the same volume ID // - Ceph RBD forbids if any two pods share at least same monitor, and match pool and image, and the image is read-only // - ISCSI forbids if any two pods share at least same IQN and ISCSI volume is read-only </ins> func (pl *VolumeRestrictions) Filter(ctx context.Context, _ *framework.CycleState, pod *v1.Pod, nodeInfo *nodeinfo.NodeInfo) *framework.Status { <del> // metadata is not needed for NoDiskConflict _, reasons, err := predicates.NoDiskConflict(pod, nil, nodeInfo) return migration.PredicateResultToFrameworkStatus(reasons, err) </del> <ins> for _, v := range pod.Spec.Volumes { for _, ev := range nodeInfo.Pods() { if isVolumeConflict(v, ev) { return framework.NewStatus(framework.Unschedulable, predicates.ErrDiskConflict.GetReason()) } } } return nil </ins> } // New initializes a new plugin and returns it.


fs.IPVar(&s.BindAddress, "bind-address", s.BindAddress, ""+ "The IP address on which to listen for the --secure-port port. The "+ "associated interface(s) must be reachable by the rest of the cluster, and by CLI/web "+ <del> "clients. If blank, all interfaces will be used (0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).") </del> <ins> "clients. If blank or an unspecified address (0.0.0.0 or ::), all interfaces will be used.") </ins> desc := "The port on which to serve HTTPS with authentication and authorization." if s.Required {


// shouldRetryHTTPRequest determines if the request is retriable. func shouldRetryHTTPRequest(resp *http.Response, err error) bool { if resp != nil { <del> // HTTP 412 (StatusPreconditionFailed) means etag mismatch, hence we shouldn't retry. if resp.StatusCode == http.StatusPreconditionFailed { </del> <ins> // HTTP 412 (StatusPreconditionFailed) means etag mismatch // HTTP 400 (BadRequest) means the request cannot be accepted, hence we shouldn't retry. if resp.StatusCode == http.StatusPreconditionFailed || resp.StatusCode == http.StatusBadRequest { </ins> return false }


{ code: http.StatusBadRequest, expected: &Error{ <del> Retriable:      true, </del> <ins> Retriable:      false, </ins> HTTPStatusCode: http.StatusBadRequest, RawError:       fmt.Errorf("HTTP response: 400"), },


}{ { code:     http.StatusBadRequest, <del> expected: true, </del> <ins> expected: false, </ins> }, { code:     http.StatusInternalServerError,


ginkgo.It("each node by switching off the network interface and ensure they function upon switch on", func() { // switch the network interface off for a while to simulate a network outage // We sleep 10 seconds to give some time for ssh command to cleanly finish before network is down. <del> testReboot(f.ClientSet, "nohup sh -c 'sleep 10 && sudo ip link set eth0 down && sleep 120 && sudo ip link set eth0 up && (sudo dhclient || true)' >/dev/null 2>&1 &", nil) </del> <ins> cmd := "nohup sh -c '" + "sleep 10; " + "echo Shutting down eth0 | sudo tee /dev/kmsg; " + "sudo ip link set eth0 down | sudo tee /dev/kmsg; " + "sleep 120; " + "echo Starting up eth0 | sudo tee /dev/kmsg; " + "sudo ip link set eth0 up | sudo tee /dev/kmsg; " + "sleep 10; " + "echo Retrying starting up eth0 | sudo tee /dev/kmsg; " + "sudo ip link set eth0 up | sudo tee /dev/kmsg; " + "echo Running dhclient | sudo tee /dev/kmsg; " + "sudo dhclient | sudo tee /dev/kmsg; " + "echo Starting systemd-networkd | sudo tee /dev/kmsg; " + "sudo systemctl restart systemd-networkd | sudo tee /dev/kmsg" + "' >/dev/null 2>&1 &" testReboot(f.ClientSet, cmd, nil) </ins> }) ginkgo.It("each node by dropping all inbound packets for a while and ensure they function afterwards", func() {


} func (s *Plugin) mountServiceAccountToken(serviceAccount *corev1.ServiceAccount, pod *api.Pod) error { <del> // Find the name of a referenced ServiceAccountToken secret we can mount serviceAccountToken, err := s.getReferencedServiceAccountToken(serviceAccount) if err != nil { return fmt.Errorf("Error looking up service account token for %s/%s: %v", serviceAccount.Namespace, serviceAccount.Name, err) </del> <ins> var ( // serviceAccountToken holds the name of a secret containing a legacy service account token serviceAccountToken string err                 error ) if !s.boundServiceAccountTokenVolume { // Find the name of a referenced ServiceAccountToken secret we can mount serviceAccountToken, err = s.getReferencedServiceAccountToken(serviceAccount) if err != nil { return fmt.Errorf("Error looking up service account token for %s/%s: %v", serviceAccount.Namespace, serviceAccount.Name, err) } </ins> } <del> if len(serviceAccountToken) == 0 { </del> <ins> if len(serviceAccountToken) == 0 && !s.boundServiceAccountTokenVolume { </ins> // We don't have an API token to mount, so return if s.RequireAPIToken { // If a token is required, this is considered an error


"k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" <ins> "k8s.io/apimachinery/pkg/util/diff" </ins> "k8s.io/apiserver/pkg/admission" admissiontesting "k8s.io/apiserver/pkg/admission/testing" "k8s.io/client-go/informers"


} } <ins> func TestAssignsDefaultServiceAccountAndBoundTokenWithNoSecretTokens(t *testing.T) { ns := "myns" admit := NewServiceAccount() informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc()) admit.SetExternalKubeInformerFactory(informerFactory) admit.MountServiceAccountToken = true admit.RequireAPIToken = true admit.boundServiceAccountTokenVolume = true // Add the default service account for the ns into the cache informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Name:      DefaultServiceAccountName, Namespace: ns, }, }) pod := &api.Pod{ Spec: api.PodSpec{ Containers: []api.Container{{}}, }, } attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil) if err != nil { t.Fatalf("Expected success, got: %v", err) } expectedVolumes := []api.Volume{{ Name: "cleared", VolumeSource: api.VolumeSource{ Projected: &api.ProjectedVolumeSource{ Sources: []api.VolumeProjection{ {ServiceAccountToken: &api.ServiceAccountTokenProjection{ExpirationSeconds: 3600, Path: "token"}}, {ConfigMap: &api.ConfigMapProjection{LocalObjectReference: api.LocalObjectReference{Name: "kube-root-ca.crt"}, Items: []api.KeyToPath{{Key: "ca.crt", Path: "ca.crt"}}}}, {DownwardAPI: &api.DownwardAPIProjection{Items: []api.DownwardAPIVolumeFile{{Path: "namespace", FieldRef: &api.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}}}, }, }, }, }} expectedVolumeMounts := []api.VolumeMount{{ Name:      "cleared", ReadOnly:  true, MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }} // clear generated volume names for i := range pod.Spec.Volumes { if len(pod.Spec.Volumes[i].Name) > 0 { pod.Spec.Volumes[i].Name = "cleared" } } for i := range pod.Spec.Containers[0].VolumeMounts { if len(pod.Spec.Containers[0].VolumeMounts[i].Name) > 0 { pod.Spec.Containers[0].VolumeMounts[i].Name = "cleared" } } if !reflect.DeepEqual(expectedVolumes, pod.Spec.Volumes) { t.Errorf("unexpected volumes: %s", diff.ObjectReflectDiff(expectedVolumes, pod.Spec.Volumes)) } if !reflect.DeepEqual(expectedVolumeMounts, pod.Spec.Containers[0].VolumeMounts) { t.Errorf("unexpected volumes: %s", diff.ObjectReflectDiff(expectedVolumeMounts, pod.Spec.Containers[0].VolumeMounts)) } } </ins> func TestFetchesUncachedServiceAccount(t *testing.T) { ns := "myns"


return status, true, nil } <del> func getPublicIPDomainNameLabel(service *v1.Service) string { </del> <ins> func getPublicIPDomainNameLabel(service *v1.Service) (string, bool) { </ins> if labelName, found := service.Annotations[ServiceAnnotationDNSLabelName]; found { <del> return labelName </del> <ins> return labelName, found </ins> } <del> return "" </del> <ins> return "", false </ins> } // EnsureLoadBalancer creates a new load balancer 'name', or updates the existing one. Returns the status of the balancer


return lbStatus.Ingress[0].IP, nil } <del> func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domainNameLabel, clusterName string, shouldPIPExisted bool) (*network.PublicIPAddress, error) { </del> <ins> func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domainNameLabel, clusterName string, shouldPIPExisted, foundDNSLabelAnnotation bool) (*network.PublicIPAddress, error) { </ins> pipResourceGroup := az.getPublicIPAddressResourceGroup(service) pip, existsPip, err := az.getPublicIPAddress(pipResourceGroup, pipName) if err != nil {


} klog.V(2).Infof("ensurePublicIPExists for service(%s): pip(%s) - creating", serviceName, *pip.Name) } <del> if len(domainNameLabel) == 0 { pip.PublicIPAddressPropertiesFormat.DNSSettings = nil } else { pip.PublicIPAddressPropertiesFormat.DNSSettings = &network.PublicIPAddressDNSSettings{ DomainNameLabel: &domainNameLabel, </del> <ins> if foundDNSLabelAnnotation { if len(domainNameLabel) == 0 { pip.PublicIPAddressPropertiesFormat.DNSSettings = nil } else { pip.PublicIPAddressPropertiesFormat.DNSSettings = &network.PublicIPAddressDNSSettings{ DomainNameLabel: &domainNameLabel, } </ins> } }


if err != nil { return nil, err } <del> domainNameLabel := getPublicIPDomainNameLabel(service) pip, err := az.ensurePublicIPExists(service, pipName, domainNameLabel, clusterName, shouldPIPExisted) </del> <ins> domainNameLabel, found := getPublicIPDomainNameLabel(service) pip, err := az.ensurePublicIPExists(service, pipName, domainNameLabel, clusterName, shouldPIPExisted, found) </ins> if err != nil { return nil, err }


if !isInternal && wantLb { // Confirm desired public ip resource exists var pip *network.PublicIPAddress <del> domainNameLabel := getPublicIPDomainNameLabel(service) if pip, err = az.ensurePublicIPExists(service, desiredPipName, domainNameLabel, clusterName, shouldPIPExisted); err != nil { </del> <ins> domainNameLabel, found := getPublicIPDomainNameLabel(service) if pip, err = az.ensurePublicIPExists(service, desiredPipName, domainNameLabel, clusterName, shouldPIPExisted, found); err != nil { </ins> return nil, err } return pip, nil


pip, err := az.reconcilePublicIP("testCluster", &service, "", test.wantLb) if test.expectedID != "" { assert.Equal(t, test.expectedID, to.String(pip.ID), "TestCase[%d]: %s", i, test.desc) <del> } else { assert.Equal(t, test.expectedPIP, pip, "TestCase[%d]: %s", i, test.desc) </del> <ins> } else if test.expectedPIP != nil && test.expectedPIP.Name != nil { assert.Equal(t, *test.expectedPIP.Name, *pip.Name, "TestCase[%d]: %s", i, test.desc) </ins> } assert.Equal(t, test.expectedError, err != nil, "TestCase[%d]: %s", i, test.desc) }


func TestEnsurePublicIPExists(t *testing.T) { testCases := []struct { <del> desc          string existingPIPs  []network.PublicIPAddress expectedPIP   *network.PublicIPAddress expectedID    string expectedDNS   string expectedError bool </del> <ins> desc                    string existingPIPs            []network.PublicIPAddress inputDNSLabel           string foundDNSLabelAnnotation bool expectedPIP             *network.PublicIPAddress expectedID              string expectedError           bool </ins> }{ { desc:         "ensurePublicIPExists shall return existed PIP if there is any",


"Microsoft.Network/publicIPAddresses/pip1", }, { <del> desc: "ensurePublicIPExists shall update existed PIP's dns label", </del> <ins> desc:                    "ensurePublicIPExists shall update existed PIP's dns label", inputDNSLabel:           "newdns", foundDNSLabelAnnotation: true, </ins> existingPIPs: []network.PublicIPAddress{{ Name: to.StringPtr("pip1"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{


}, }, }, <del> expectedDNS: "newdns", </del> <ins> }, { desc:                    "ensurePublicIPExists shall delete DNS from PIP if DNS label is set empty", foundDNSLabelAnnotation: true, existingPIPs: []network.PublicIPAddress{{ Name: to.StringPtr("pip1"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ DNSSettings: &network.PublicIPAddressDNSSettings{ DomainNameLabel: to.StringPtr("previousdns"), }, }, }}, expectedPIP: &network.PublicIPAddress{ Name: to.StringPtr("pip1"), ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg" + "/providers/Microsoft.Network/publicIPAddresses/pip1"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ DNSSettings: nil, }, }, }, { desc:                    "ensurePublicIPExists shall not delete DNS from PIP if DNS label annotation is not set", foundDNSLabelAnnotation: false, existingPIPs: []network.PublicIPAddress{{ Name: to.StringPtr("pip1"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ DNSSettings: &network.PublicIPAddressDNSSettings{ DomainNameLabel: to.StringPtr("previousdns"), }, }, }}, expectedPIP: &network.PublicIPAddress{ Name: to.StringPtr("pip1"), ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg" + "/providers/Microsoft.Network/publicIPAddresses/pip1"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ DNSSettings: &network.PublicIPAddressDNSSettings{ DomainNameLabel: to.StringPtr("previousdns"), }, }, }, </ins> }, }


t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } } <del> pip, err := az.ensurePublicIPExists(&service, "pip1", test.expectedDNS, "", false) </del> <ins> pip, err := az.ensurePublicIPExists(&service, "pip1", test.inputDNSLabel, "", false, test.foundDNSLabelAnnotation) </ins> if test.expectedID != "" { assert.Equal(t, test.expectedID, to.String(pip.ID), "TestCase[%d]: %s", i, test.desc) } else {


else bazel-release: bazel build //build/release-tars <ins> bazel shutdown </ins> endif


if len(name) == 0 { _, name, _ = scope.Namer.ObjectName(obj) } <del> admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, options, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) { err = mutatingAdmission.Admit(ctx, admissionAttributes, scope) if err != nil { scope.err(err, w, req) return } } if scope.FieldManager != nil { liveObj, err := scope.Creater.New(scope.Kind) if err != nil { scope.err(fmt.Errorf("failed to create new object (Create for %v): %v", scope.Kind, err), w, req) return </del> <ins> trace.Step("About to store object in database") result, err := finishRequest(timeout, func() (runtime.Object, error) { if scope.FieldManager != nil { liveObj, err := scope.Creater.New(scope.Kind) if err != nil { return nil, fmt.Errorf("failed to create new object (Create for %v): %v", scope.Kind, err) } obj, err = scope.FieldManager.Update(liveObj, obj, managerOrUserAgent(options.FieldManager, req.UserAgent())) if err != nil { return nil, fmt.Errorf("failed to update object (Create for %v) managed fields: %v", scope.Kind, err) } </ins> } <del> obj, err = scope.FieldManager.Update(liveObj, obj, managerOrUserAgent(options.FieldManager, req.UserAgent())) if err != nil { scope.err(fmt.Errorf("failed to update object (Create for %v) managed fields: %v", scope.Kind, err), w, req) return </del> <ins> admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, options, dryrun.IsDryRun(options.DryRun), userInfo) if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) { if err := mutatingAdmission.Admit(ctx, admissionAttributes, scope); err != nil { return nil, err } </ins> } <del> } trace.Step("About to store object in database") result, err := finishRequest(timeout, func() (runtime.Object, error) { </del> return r.Create( ctx, name,


leaveStdinOpen := o.LeaveStdinOpen waitForExitCode := !leaveStdinOpen && restartPolicy == corev1.RestartPolicyNever if waitForExitCode { <del> pod, err = waitForPod(clientset.CoreV1(), attachablePod.Namespace, attachablePod.Name, podCompleted) </del> <ins> pod, err = waitForPod(clientset.CoreV1(), attachablePod.Namespace, attachablePod.Name, opts.GetPodTimeout, podCompleted) </ins> if err != nil { return err }


} // waitForPod watches the given pod until the exitCondition is true <del> func waitForPod(podClient corev1client.PodsGetter, ns, name string, exitCondition watchtools.ConditionFunc) (*corev1.Pod, error) { // TODO: expose the timeout ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), 0*time.Second) </del> <ins> func waitForPod(podClient corev1client.PodsGetter, ns, name string, timeout time.Duration, exitCondition watchtools.ConditionFunc) (*corev1.Pod, error) { ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout) </ins> defer cancel() preconditionFunc := func(store cache.Store) (bool, error) {


} func handleAttachPod(f cmdutil.Factory, podClient corev1client.PodsGetter, ns, name string, opts *attach.AttachOptions) error { <del> pod, err := waitForPod(podClient, ns, name, podRunningAndReady) </del> <ins> pod, err := waitForPod(podClient, ns, name, opts.GetPodTimeout, podRunningAndReady) </ins> if err != nil && err != ErrPodCompleted { return err }


ctx, cancel := watchtools.ContextWithOptionalTimeout(ctx, 0*time.Second) defer cancel() <del> preconditionFunc := func(store cache.Store) (bool, error) { _, exists, err := store.Get(&metav1.ObjectMeta{Namespace: ns, Name: podName}) if err != nil { return true, err } if !exists { // We need to make sure we see the object in the cache before we start waiting for events // or we would be waiting for the timeout if such object didn't exist. // (e.g. it was deleted before we started informers so they wouldn't even see the delete event) return true, errors.NewNotFound(corev1.Resource("pods"), podName) } return false, nil } </del> fieldSelector := fields.OneTermEqualSelector("metadata.name", podName).String() lw := &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {


intr := interrupt.New(nil, cancel) var result *corev1.Pod err := intr.Run(func() error { <del> ev, err := watchtools.UntilWithSync(ctx, lw, &corev1.Pod{}, preconditionFunc, func(ev watch.Event) (bool, error) { </del> <ins> ev, err := watchtools.UntilWithSync(ctx, lw, &corev1.Pod{}, nil, func(ev watch.Event) (bool, error) { </ins> switch ev.Type { case watch.Deleted: return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "")


"//build/visible_to:pkg_kubectl_cmd_rollout_CONSUMERS", ], deps = [ <del> "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", </del> "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",


"github.com/spf13/cobra" <del> apierrors "k8s.io/apimachinery/pkg/api/errors" </del> "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"


}, } <del> preconditionFunc := func(store cache.Store) (bool, error) { _, exists, err := store.Get(&metav1.ObjectMeta{Namespace: info.Namespace, Name: info.Name}) if err != nil { return true, err } if !exists { // We need to make sure we see the object in the cache before we start waiting for events // or we would be waiting for the timeout if such object didn't exist. return true, apierrors.NewNotFound(mapping.Resource.GroupResource(), info.Name) } return false, nil } </del> // if the rollout isn't done yet, keep watching deployment status ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), o.Timeout) intr := interrupt.New(nil, cancel) return intr.Run(func() error { <del> _, err = watchtools.UntilWithSync(ctx, lw, &unstructured.Unstructured{}, preconditionFunc, func(e watch.Event) (bool, error) { </del> <ins> _, err = watchtools.UntilWithSync(ctx, lw, &unstructured.Unstructured{}, nil, func(e watch.Event) (bool, error) { </ins> switch t := e.Type; t { case watch.Added, watch.Modified: status, done, err := statusViewer.Status(e.Object.(runtime.Unstructured), o.Revision)


} var pod *corev1.Pod <del> leaveStdinOpen := o.LeaveStdinOpen waitForExitCode := !leaveStdinOpen && restartPolicy == corev1.RestartPolicyNever </del> <ins> waitForExitCode := !o.LeaveStdinOpen && (restartPolicy == corev1.RestartPolicyNever || restartPolicy == corev1.RestartPolicyOnFailure) </ins> if waitForExitCode { <del> pod, err = waitForPod(clientset.CoreV1(), attachablePod.Namespace, attachablePod.Name, opts.GetPodTimeout, podCompleted) </del> <ins> // we need different exit condition depending on restart policy // for Never it can either fail or succeed, for OnFailure only // success matters exitCondition := podCompleted if restartPolicy == corev1.RestartPolicyOnFailure { exitCondition = podSucceeded } pod, err = waitForPod(clientset.CoreV1(), attachablePod.Namespace, attachablePod.Name, opts.GetPodTimeout, exitCondition) </ins> if err != nil { return err } <del> } // after removal is done, return successfully if we are not interested in the exit code if !waitForExitCode { </del> <ins> } else { // after removal is done, return successfully if we are not interested in the exit code </ins> return nil }


ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout) defer cancel() <del> preconditionFunc := func(store cache.Store) (bool, error) { _, exists, err := store.Get(&metav1.ObjectMeta{Namespace: ns, Name: name}) if err != nil { return true, err } if !exists { // We need to make sure we see the object in the cache before we start waiting for events // or we would be waiting for the timeout if such object didn't exist. // (e.g. it was deleted before we started informers so they wouldn't even see the delete event) return true, errors.NewNotFound(corev1.Resource("pods"), name) } return false, nil } </del> fieldSelector := fields.OneTermEqualSelector("metadata.name", name).String() lw := &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {


intr := interrupt.New(nil, cancel) var result *corev1.Pod err := intr.Run(func() error { <del> ev, err := watchtools.UntilWithSync(ctx, lw, &corev1.Pod{}, preconditionFunc, func(ev watch.Event) (bool, error) { return exitCondition(ev) }) </del> <ins> ev, err := watchtools.UntilWithSync(ctx, lw, &corev1.Pod{}, nil, exitCondition) </ins> if ev != nil { result = ev.Object.(*corev1.Pod) }


return false, nil } <ins> // podSucceeded returns true if the pod has run to completion, false if the pod has not yet // reached running state, or an error in any other case. func podSucceeded(event watch.Event) (bool, error) { switch event.Type { case watch.Deleted: return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "") } switch t := event.Object.(type) { case *corev1.Pod: return t.Status.Phase == corev1.PodSucceeded, nil } return false, nil } </ins> // podRunningAndReady returns true if the pod is running and ready, false if the pod has not // yet reached those states, returns ErrPodCompleted if the pod has run to completion, or // an error in any other case.


_, err = framework.NewKubectlCommand(ns, nsFlag, "run", "-i", "--image="+busyboxImage, "--restart=OnFailure", "failure-2", "--", "/bin/sh", "-c", "cat && exit 42"). WithStdinData("abcd1234"). Exec() <del> framework.ExpectNoError(err) </del> <ins> ee, ok = err.(uexec.ExitError) framework.ExpectEqual(ok, true) if !strings.Contains(ee.String(), "timed out") { framework.Failf("Missing expected 'timed out' error, got: %#v", ee) } </ins> ginkgo.By("running a failing command without --restart=Never, but with --rm") _, err = framework.NewKubectlCommand(ns, nsFlag, "run", "-i", "--image="+busyboxImage, "--restart=OnFailure", "--rm", "failure-3", "--", "/bin/sh", "-c", "cat && exit 42"). WithStdinData("abcd1234"). Exec() <del> framework.ExpectNoError(err) </del> <ins> ee, ok = err.(uexec.ExitError) framework.ExpectEqual(ok, true) if !strings.Contains(ee.String(), "timed out") { framework.Failf("Missing expected 'timed out' error, got: %#v", ee) } </ins> e2epod.WaitForPodToDisappear(f.ClientSet, ns, "failure-3", labels.Everything(), 2*time.Second, wait.ForeverTestTimeout) ginkgo.By("running a failing command with --leave-stdin-open")


UseEndpointSlices      bool OOMScoreAdj            *int32 ConfigSyncPeriod       time.Duration <del> HealthzServer          *healthcheck.ProxierHealthServer </del> <ins> HealthzServer          healthcheck.ProxierHealthUpdater </ins> } // createClients creates a kube client and an event client from the given config and masterOverride.


Namespace: "", } <del> var healthzServer *healthcheck.ProxierHealthServer </del> <ins> var healthzServer healthcheck.ProxierHealthUpdater </ins> if len(config.HealthzBindAddress) > 0 { healthzServer = healthcheck.NewProxierHealthServer(config.HealthzBindAddress, 2*config.IPTables.SyncPeriod.Duration, recorder, nodeRef) }


// Updated should be called when the proxier has successfully updated the service // rules to reflect the current state. Updated() <ins> // Run starts the healthz http server and returns. Run() </ins> } <del> var _ ProxierHealthUpdater = &ProxierHealthServer{} </del> <ins> var _ ProxierHealthUpdater = &proxierHealthServer{} </ins> <del> // ProxierHealthServer returns 200 "OK" by default. It verifies that the delay between </del> <ins> // proxierHealthServer returns 200 "OK" by default. It verifies that the delay between </ins> // QueuedUpdate() calls and Updated() calls never exceeds healthTimeout. <del> type ProxierHealthServer struct { </del> <ins> type proxierHealthServer struct { </ins> listener    listener httpFactory httpServerFactory clock       clock.Clock


} // NewProxierHealthServer returns a proxier health http server. <del> func NewProxierHealthServer(addr string, healthTimeout time.Duration, recorder record.EventRecorder, nodeRef *v1.ObjectReference) *ProxierHealthServer { </del> <ins> func NewProxierHealthServer(addr string, healthTimeout time.Duration, recorder record.EventRecorder, nodeRef *v1.ObjectReference) ProxierHealthUpdater { </ins> return newProxierHealthServer(stdNetListener{}, stdHTTPServerFactory{}, clock.RealClock{}, addr, healthTimeout, recorder, nodeRef) } <del> func newProxierHealthServer(listener listener, httpServerFactory httpServerFactory, c clock.Clock, addr string, healthTimeout time.Duration, recorder record.EventRecorder, nodeRef *v1.ObjectReference) *ProxierHealthServer { return &ProxierHealthServer{ </del> <ins> func newProxierHealthServer(listener listener, httpServerFactory httpServerFactory, c clock.Clock, addr string, healthTimeout time.Duration, recorder record.EventRecorder, nodeRef *v1.ObjectReference) *proxierHealthServer { return &proxierHealthServer{ </ins> listener:      listener, httpFactory:   httpServerFactory, clock:         c,


} // Updated updates the lastUpdated timestamp. <del> func (hs *ProxierHealthServer) Updated() { </del> <ins> func (hs *proxierHealthServer) Updated() { </ins> hs.lastUpdated.Store(hs.clock.Now()) } // QueuedUpdate updates the lastQueued timestamp. <del> func (hs *ProxierHealthServer) QueuedUpdate() { </del> <ins> func (hs *proxierHealthServer) QueuedUpdate() { </ins> hs.lastQueued.Store(hs.clock.Now()) } // Run starts the healthz http server and returns. <del> func (hs *ProxierHealthServer) Run() { </del> <ins> func (hs *proxierHealthServer) Run() { </ins> serveMux := http.NewServeMux() serveMux.Handle("/healthz", healthzHandler{hs: hs}) server := hs.httpFactory.New(hs.addr, serveMux)


} type healthzHandler struct { <del> hs *ProxierHealthServer </del> <ins> hs *proxierHealthServer </ins> } func (h healthzHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {


// trigger a new deployment framework.Logf("%02d: triggering a new rollout for deployment %q", i, deployment.Name) deployment, err = e2edeployment.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *appsv1.Deployment) { <del> newEnv := v1.EnvVar{Name: "A", Value: fmt.Sprintf("%d", i)} </del> <ins> newEnv := v1.EnvVar{Name: fmt.Sprintf("A%d", i), Value: fmt.Sprintf("%d", i)} </ins> update.Spec.Template.Spec.Containers[0].Env = append(update.Spec.Template.Spec.Containers[0].Env, newEnv) randomScale(update, i) })


// only return the user provided mode if at least one was valid if len(mode) > 0 { <del> klog.Warningf("the default kube-apiserver authorization-mode is %q; using %q", strings.Join(defaultMode, ","), strings.Join(mode, ","), ) </del> <ins> if !compareAuthzModes(defaultMode, mode) { klog.Warningf("the default kube-apiserver authorization-mode is %q; using %q", strings.Join(defaultMode, ","), strings.Join(mode, ","), ) } </ins> return strings.Join(mode, ",") } } return strings.Join(defaultMode, ",") } <ins> // compareAuthzModes compares two given authz modes and returns false if they do not match func compareAuthzModes(a, b []string) bool { if len(a) != len(b) { return false } for i, m := range a { if m != b[i] { return false } } return true } </ins> func isValidAuthzMode(authzMode string) bool { allModes := []string{ kubeadmconstants.ModeNode,


}) } } <ins> func TestCompareAuthzModes(t *testing.T) { var tests = []struct { name   string modesA []string modesB []string equal  bool }{ { name:   "modes match", modesA: []string{"a", "b", "c"}, modesB: []string{"a", "b", "c"}, equal:  true, }, { name:   "modes order does not match", modesA: []string{"a", "c", "b"}, modesB: []string{"a", "b", "c"}, }, { name:   "modes do not match; A has less modes", modesA: []string{"a", "b"}, modesB: []string{"a", "b", "c"}, }, { name:   "modes do not match; B has less modes", modesA: []string{"a", "b", "c"}, modesB: []string{"a", "b"}, }, } for _, rt := range tests { t.Run(rt.name, func(t *testing.T) { equal := compareAuthzModes(rt.modesA, rt.modesB) if equal != rt.equal { t.Errorf("failed compareAuthzModes:nexpected:n%vnsaw:n%v", rt.equal, equal) } }) } } </ins>


} orphan := false switch { <ins> case options.OrphanDependents == nil && options.PropagationPolicy == nil && len(initialFinalizers) == 0: // if there are no deletion options, the default policy for replication controllers is orphan orphan = true </ins> case options.OrphanDependents != nil: // if the deletion options explicitly specify whether to orphan, that controls orphan = *options.OrphanDependents


return false } <del> if c.spec.PersistentVolume == nil { klog.V(4).Info(log("mounter.SetupAt Warning: skipping fsGroup permission change, no access mode available. The volume may only be accessible to root users.")) return false } if c.spec.PersistentVolume.Spec.AccessModes == nil { klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, access modes not provided")) return false } if !hasReadWriteOnce(c.spec.PersistentVolume.Spec.AccessModes) { klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, only support ReadWriteOnce access mode")) return false </del> <ins> if c.spec.PersistentVolume != nil { if c.spec.PersistentVolume.Spec.AccessModes == nil { klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, access modes not provided")) return false } if !hasReadWriteOnce(c.spec.PersistentVolume.Spec.AccessModes) { klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, only support ReadWriteOnce access mode")) return false } return true } else if c.spec.Volume != nil && c.spec.Volume.CSI != nil { if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) { klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, CSIInlineVolume feature required")) return false } // Inline CSI volumes are always mounted with RWO AccessMode by SetUpAt return true </ins> } <del> return true </del> <ins> klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, unsupported volume type")) return false </ins> } // isDirMounted returns the !notMounted result from IsLikelyNotMountPoint check


}, want: true, }, <ins> { name: "driverPolicy is ReadWriteOnceWithFSTypeFSGroupPolicy with CSI inline volume", args: args{ fsGroup:      new(int64), fsType:       "ext4", driverPolicy: storage.ReadWriteOnceWithFSTypeFSGroupPolicy, }, fields: fields{ spec: volume.NewSpecFromVolume(&api.Volume{ VolumeSource: api.VolumeSource{ CSI: &api.CSIVolumeSource{ Driver: testDriver, }, }, }), }, want: true, }, </ins> } for _, tt := range tests {


// The filter doesn't filter out any object. wc.internalPred = storage.Everything } <del> wc.ctx, wc.cancel = context.WithCancel(ctx) </del> <ins> // The etcd server waits until it cannot find a leader for 3 election // timeouts to cancel existing streams. 3 is currently a hard coded // constant. The election timeout defaults to 1000ms. If the cluster is // healthy, when the leader is stopped, the leadership transfer should be // smooth. (leader transfers its leadership before stopping). If leader is // hard killed, other servers will take an election timeout to realize // leader lost and start campaign. wc.ctx, wc.cancel = context.WithCancel(clientv3.WithRequireLeader(ctx)) </ins> return wc }


github.com/lpabon/godbc v0.1.1 // indirect github.com/magiconair/properties v1.8.1 // indirect github.com/miekg/dns v1.1.4 <del> github.com/moby/ipvs v1.0.0 </del> <ins> github.com/moby/ipvs v1.0.1 </ins> github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb // indirect github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822


github.com/mitchellh/go-homedir => github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-wordwrap => github.com/mitchellh/go-wordwrap v1.0.0 github.com/mitchellh/mapstructure => github.com/mitchellh/mapstructure v1.1.2 <del> github.com/moby/ipvs => github.com/moby/ipvs v1.0.0 </del> <ins> github.com/moby/ipvs => github.com/moby/ipvs v1.0.1 </ins> github.com/moby/term => github.com/moby/term v0.0.0-20200312100748-672ec06f55cd github.com/modern-go/concurrent => github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd github.com/modern-go/reflect2 => github.com/modern-go/reflect2 v1.0.1


github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= <del> github.com/moby/ipvs v1.0.0 h1:89i8bPaL2DC0cjyRDv0QQOYUOU4fujziJmhF4ca/mtY= github.com/moby/ipvs v1.0.0/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= </del> <ins> github.com/moby/ipvs v1.0.1 h1:aoZ7fhLTXgDbzVrAnvV+XbKOU8kOET7B3+xULDF/1o0= github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= </ins> github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=


import ( "bytes" "encoding/binary" <ins> "errors" </ins> "fmt" "net" "os/exec"


d.ActiveConnections = int(native.Uint16(attr.Value)) case ipvsDestAttrInactiveConnections: d.InactiveConnections = int(native.Uint16(attr.Value)) <del> case ipvsSvcAttrStats: </del> <ins> case ipvsDestAttrStats: </ins> stats, err := assembleStats(attr.Value) if err != nil { return nil, err


} } <ins> // in older kernels (< 3.18), the destination address family attribute doesn't exist so we must // assume it based on the destination address provided. if d.AddressFamily == 0 { // we can't check the address family using net stdlib because netlink returns // IPv4 addresses as the first 4 bytes in a []byte of length 16 where as // stdlib expects it as the last 4 bytes. addressFamily, err := getIPFamily(addressBytes) if err != nil { return nil, err } d.AddressFamily = addressFamily } </ins> // parse Address after parse AddressFamily incase of parseIP error if addressBytes != nil { ip, err := parseIP(addressBytes, d.AddressFamily)


return &d, nil } <ins> // getIPFamily parses the IP family based on raw data from netlink. // For AF_INET, netlink will set the first 4 bytes with trailing zeros //   10.0.0.1 -> [10 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] // For AF_INET6, the full 16 byte array is used: //   2001:db8:3c4d:15::1a00 -> [32 1 13 184 60 77 0 21 0 0 0 0 0 0 26 0] func getIPFamily(address []byte) (uint16, error) { if len(address) == 4 { return syscall.AF_INET, nil } if isZeros(address) { return 0, errors.New("could not parse IP family from address data") } // assume IPv4 if first 4 bytes are non-zero but rest of the data is trailing zeros if !isZeros(address[:4]) && isZeros(address[4:]) { return syscall.AF_INET, nil } return syscall.AF_INET6, nil } func isZeros(b []byte) bool { for i := 0; i < len(b); i++ { if b[i] != 0 { return false } } return true } </ins> // parseDestination given a ipvs netlink response this function will respond with a valid destination entry, an error otherwise func (i *Handle) parseDestination(msg []byte) (*Destination, error) { var dst *Destination


github.com/mitchellh/go-wordwrap # github.com/mitchellh/mapstructure v1.1.2 => github.com/mitchellh/mapstructure v1.1.2 github.com/mitchellh/mapstructure <del> # github.com/moby/ipvs v1.0.0 => github.com/moby/ipvs v1.0.0 </del> <ins> # github.com/moby/ipvs v1.0.1 => github.com/moby/ipvs v1.0.1 </ins> github.com/moby/ipvs # github.com/moby/term v0.0.0-20200312100748-672ec06f55cd => github.com/moby/term v0.0.0-20200312100748-672ec06f55cd github.com/moby/term


expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") // .status.num should be 999 expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num")    // .spec.num should remain 10 <del> rv, found, err := unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") if err != nil { t.Fatal(err) } if !found { t.Fatalf("metadata.resourceVersion not found") } // this call waits for the resourceVersion to be reached in the cache before returning. // We need to do this because the patch gets its initial object from the storage, and the cache serves that. // If it is out of date, then our initial patch is applied to an old resource version, which conflicts // and then the updated object shows a conflicting diff, which permanently fails the patch. // This gives expected stability in the patch without retrying on an known number of conflicts below in the test. // See https://issue.k8s.io/42644 _, err = noxuResourceClient.Get(context.TODO(), "foo", metav1.GetOptions{ResourceVersion: patchedNoxuInstance.GetResourceVersion()}) if err != nil { t.Fatalf("unexpected error: %v", err) } </del> // no-op patch <del> t.Logf("Patching .status.num again to 999") patchedNoxuInstance, err = noxuResourceClient.Patch(context.TODO(), "foo", types.MergePatchType, patch, metav1.PatchOptions{}, "status") if err != nil { t.Fatalf("unexpected error: %v", err) </del> <ins> rv := "" found := false // TODO: remove this retry once http://issue.k8s.io/75564 is resolved, and expect the resourceVersion to remain unchanged 100% of the time. // server-side-apply incorrectly considers spec fields in patches submitted to /status when updating managedFields timestamps, so this patch is racy: // if it spans a 1-second boundary from the last write, server-side-apply updates the managedField timestamp and increments resourceVersion. for i := 0; i < 10; i++ { rv, found, err = unstructured.NestedString(patchedNoxuInstance.UnstructuredContent(), "metadata", "resourceVersion") if err != nil { t.Fatal(err) } if !found { t.Fatalf("metadata.resourceVersion not found") } t.Logf("Patching .status.num again to 999") patchedNoxuInstance, err = noxuResourceClient.Patch(context.TODO(), "foo", types.MergePatchType, patch, metav1.PatchOptions{}, "status") if err != nil { t.Fatalf("unexpected error: %v", err) } // make sure no-op patch does not increment resourceVersion expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") if patchedNoxuInstance.GetResourceVersion() == rv { break } t.Logf("resource version changed - retrying") </ins> } <del> // make sure no-op patch does not increment resourceVersion expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 999, "status", "num") expectInt64(t, patchedNoxuInstance.UnstructuredContent(), 10, "spec", "num") </del> expectString(t, patchedNoxuInstance.UnstructuredContent(), rv, "metadata", "resourceVersion") // empty patch


t.Fatalf("metadata.resourceVersion not found") } <del> // this call waits for the resourceVersion to be reached in the cache before returning. // We need to do this because the patch gets its initial object from the storage, and the cache serves that. // If it is out of date, then our initial patch is applied to an old resource version, which conflicts // and then the updated object shows a conflicting diff, which permanently fails the patch. // This gives expected stability in the patch without retrying on an known number of conflicts below in the test. // See https://issue.k8s.io/42644 _, err = noxuResourceClient.Get(context.TODO(), "foo", metav1.GetOptions{ResourceVersion: patchedNoxuInstance.GetResourceVersion()}) if err != nil { t.Fatalf("unexpected error: %v", err) } </del> // Scale.Spec.Replicas = 7 but Scale.Status.Replicas should remain 0 gottenScale, err := scaleClient.Scales("not-the-default").Get(context.TODO(), groupResource, "foo", metav1.GetOptions{}) if err != nil {


} ipvsModules := utilipvs.GetRequiredIPVSModules(kernelVersion) <del> var bmods []string </del> <ins> var bmods, lmods []string </ins> // Find out loaded kernel modules. If this is a full static kernel it will try to verify if the module is compiled using /boot/config-KERNELVERSION modulesFile, err := os.Open("/proc/modules")


if err != nil { klog.Warningf("Failed to load kernel module %v with modprobe. "+ "You can ignore this message when kube-proxy is running inside container without mounting /lib/modules", module) <ins> } else { lmods = append(lmods, module) </ins> } } } <del> return append(mods, bmods...), nil </del> <ins> mods = append(mods, bmods...) mods = append(mods, lmods...) return mods, nil </ins> } // getFirstColumn reads all the content from r into memory and return a


if pod == nil { return fmt.Errorf("pod is missing, skipping (%s/%s)", addr.TargetRef.Namespace, addr.TargetRef.Name) } <del> if pod.Status.PodIPs[0].IP != addr.IP { return fmt.Errorf("pod ip doesn't match endpoint ip, skipping: %s vs %s (%s/%s)", pod.Status.PodIPs[0].IP, addr.IP, addr.TargetRef.Namespace, addr.TargetRef.Name) </del> <ins> for _, podIP := range pod.Status.PodIPs { if podIP.IP == addr.IP { return nil } </ins> } <del> return nil </del> <ins> return fmt.Errorf("pod ip(s) doesn't match endpoint ip, skipping: %v vs %s (%s/%s)", pod.Status.PodIPs, addr.IP, addr.TargetRef.Namespace, addr.TargetRef.Name) </ins> } // This is O(N), but we expect haystack to be small;


Ports:     []api.EndpointPort{{Name: "", Port: 80}, {Name: "p", Port: 93}}, }}, }, <ins> { ObjectMeta: metav1.ObjectMeta{ Name:      "foo-second-ip", Namespace: metav1.NamespaceDefault, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "2001:db7::", TargetRef: &api.ObjectReference{Name: "foo", Namespace: metav1.NamespaceDefault}}}, Ports:     []api.EndpointPort{{Name: "", Port: 80}, {Name: "p", Port: 93}}, }}, }, </ins> }, } pods := &api.PodList{


t.Errorf("Expected %v, but got %v", e, a) } <ins> // Test a simple id (using second ip). location, _, err = redirector.ResourceLocation(ctx, "foo-second-ip") if err != nil { t.Errorf("Unexpected error: %v", err) } if location == nil { t.Errorf("Unexpected nil: %v", location) } if e, a := "//[2001:db7::]:80", location.String(); e != a { t.Errorf("Expected %v, but got %v", e, a) } </ins> // Test a name + port. location, _, err = redirector.ResourceLocation(ctx, "foo:p") if err != nil {


t.Errorf("Expected %v, but got %v", e, a) } <ins> // Test a name + port (using second ip). location, _, err = redirector.ResourceLocation(ctx, "foo-second-ip:p") if err != nil { t.Errorf("Unexpected error: %v", err) } if location == nil { t.Errorf("Unexpected nil: %v", location) } if e, a := "//[2001:db7::]:93", location.String(); e != a { t.Errorf("Expected %v, but got %v", e, a) } </ins> // Test a name + port number (service port 93 -> target port 80) location, _, err = redirector.ResourceLocation(ctx, "foo:93") if err != nil {


t.Errorf("Expected %v, but got %v", e, a) } <ins> // Test a name + port number (service port 93 -> target port 80, using second ip) location, _, err = redirector.ResourceLocation(ctx, "foo-second-ip:93") if err != nil { t.Errorf("Unexpected error: %v", err) } if location == nil { t.Errorf("Unexpected nil: %v", location) } if e, a := "//[2001:db7::]:80", location.String(); e != a { t.Errorf("Expected %v, but got %v", e, a) } </ins> // Test a name + port number (service port 9393 -> target port "p" -> endpoint port 93) location, _, err = redirector.ResourceLocation(ctx, "foo:9393") if err != nil {


t.Errorf("Expected %v, but got %v", e, a) } <ins> // Test a name + port number (service port 9393 -> target port "p" -> endpoint port 93, using second ip) location, _, err = redirector.ResourceLocation(ctx, "foo-second-ip:9393") if err != nil { t.Errorf("Unexpected error: %v", err) } if location == nil { t.Errorf("Unexpected nil: %v", location) } if e, a := "//[2001:db7::]:93", location.String(); e != a { t.Errorf("Expected %v, but got %v", e, a) } </ins> // Test a scheme + name + port. location, _, err = redirector.ResourceLocation(ctx, "https:foo:p") if err != nil {


t.Errorf("Expected %v, but got %v", e, a) } <ins> // Test a scheme + name + port (using second ip). location, _, err = redirector.ResourceLocation(ctx, "https:foo-second-ip:p") if err != nil { t.Errorf("Unexpected error: %v", err) } if location == nil { t.Errorf("Unexpected nil: %v", location) } if e, a := "https://[2001:db7::]:93", location.String(); e != a { t.Errorf("Expected %v, but got %v", e, a) } </ins> // Test a non-existent name + port. location, _, err = redirector.ResourceLocation(ctx, "foo:q") if err == nil { t.Errorf("Unexpected nil error") } <ins> // Test a non-existent name + port (using second ip). location, _, err = redirector.ResourceLocation(ctx, "foo-second-ip:q") if err == nil { t.Errorf("Unexpected nil error") } </ins> // Test error path if _, _, err = redirector.ResourceLocation(ctx, "bar"); err == nil { t.Errorf("unexpected nil error")


serviceHealthServer := healthcheck.NewServiceHealthServer(hostname, recorder) isIPv6 := ipt.IsIPv6() <ins> var incorrectAddresses []string nodePortAddresses, incorrectAddresses = utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, isIPv6) if len(incorrectAddresses) > 0 { klog.Warning("NodePortAddresses of wrong family; ", incorrectAddresses) } </ins> proxier := &Proxier{ portsMap:                 make(map[utilproxy.LocalPort]utilproxy.Closeable), serviceMap:               make(proxy.ServiceMap),


nodePortAddresses []string, ) (proxy.Provider, error) { // Create an ipv4 instance of the single-stack proxier <ins> nodePortAddresses4, nodePortAddresses6 := utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, false) </ins> ipv4Proxier, err := NewProxier(ipt[0], sysctl, exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[0], hostname, <del> nodeIP[0], recorder, healthzServer, nodePortAddresses) </del> <ins> nodeIP[0], recorder, healthzServer, nodePortAddresses4) </ins> if err != nil { return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err) } ipv6Proxier, err := NewProxier(ipt[1], sysctl, exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[1], hostname, <del> nodeIP[1], recorder, healthzServer, nodePortAddresses) </del> <ins> nodeIP[1], recorder, healthzServer, nodePortAddresses6) </ins> if err != nil { return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err) }


endpointSlicesEnabled := utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceProxying) <ins> var incorrectAddresses []string nodePortAddresses, incorrectAddresses = utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, isIPv6) if len(incorrectAddresses) > 0 { klog.Warning("NodePortAddresses of wrong family; ", incorrectAddresses) } </ins> proxier := &Proxier{ portsMap:              make(map[utilproxy.LocalPort]utilproxy.Closeable), serviceMap:            make(proxy.ServiceMap),


safeIpset := newSafeIpset(ipset) <ins> nodePortAddresses4, nodePortAddresses6 := utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, false) </ins> // Create an ipv4 instance of the single-stack proxier ipv4Proxier, err := NewProxier(ipt[0], ipvs, safeIpset, sysctl, exec, syncPeriod, minSyncPeriod, filterCIDRs(false, excludeCIDRs), strictARP, tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit, localDetectors[0], hostname, nodeIP[0], <del> recorder, healthzServer, scheduler, nodePortAddresses, kernelHandler) </del> <ins> recorder, healthzServer, scheduler, nodePortAddresses4, kernelHandler) </ins> if err != nil { return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err) }


exec, syncPeriod, minSyncPeriod, filterCIDRs(true, excludeCIDRs), strictARP, tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit, localDetectors[1], hostname, nodeIP[1], <del> nil, nil, scheduler, nodePortAddresses, kernelHandler) </del> <ins> nil, nil, scheduler, nodePortAddresses6, kernelHandler) </ins> if err != nil { return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err) }


} <ins> func TestFailedParseParamsSummaryHandler(t *testing.T) { fw := newServerTest() defer fw.testHTTPServer.Close() resp, err := http.Post(fw.testHTTPServer.URL+"/stats/summary", "invalid/content/type", nil) assert.NoError(t, err) defer resp.Body.Close() v, err := ioutil.ReadAll(resp.Body) assert.NoError(t, err) assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) assert.Contains(t, string(v), "parse form failed") } </ins> func TestTrimURLPath(t *testing.T) { tests := []struct { path, expected string


"//staging/src/k8s.io/component-base/metrics:go_default_library", "//vendor/github.com/emicklei/go-restful:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library", <ins> "//vendor/github.com/pkg/errors:go_default_library", </ins> "//vendor/k8s.io/klog:go_default_library", ], )


restful "github.com/emicklei/go-restful" cadvisorapi "github.com/google/cadvisor/info/v1" <ins> "github.com/pkg/errors" </ins> "k8s.io/klog" "k8s.io/api/core/v1"


// If "only_cpu_and_memory" GET param is true then only cpu and memory is returned in response. func (h *handler) handleSummary(request *restful.Request, response *restful.Response) { onlyCPUAndMemory := false <del> request.Request.ParseForm() </del> <ins> err := request.Request.ParseForm() if err != nil { handleError(response, "/stats/summary", errors.Wrapf(err, "parse form failed")) return } </ins> if onlyCluAndMemoryParam, found := request.Request.Form["only_cpu_and_memory"]; found && len(onlyCluAndMemoryParam) == 1 && onlyCluAndMemoryParam[0] == "true" { onlyCPUAndMemory = true } var summary *statsapi.Summary <del> var err error </del> if onlyCPUAndMemory { summary, err = h.summaryProvider.GetCPUAndMemoryStats() } else {


} // NodeAddresses is an implementation of Instances.NodeAddresses. <del> func (g *Cloud) NodeAddresses(_ context.Context, _ types.NodeName) ([]v1.NodeAddress, error) { internalIP, err := metadata.Get("instance/network-interfaces/0/ip") if err != nil { return nil, fmt.Errorf("couldn't get internal IP: %v", err) </del> <ins> func (g *Cloud) NodeAddresses(ctx context.Context, nodeName types.NodeName) ([]v1.NodeAddress, error) { timeoutCtx, cancel := context.WithTimeout(ctx, 1*time.Hour) defer cancel() instanceName := string(nodeName) if g.useMetadataServer { // Use metadata server if possible if g.isCurrentInstance(instanceName) { internalIP, err := metadata.Get("instance/network-interfaces/0/ip") if err != nil { return nil, fmt.Errorf("couldn't get internal IP: %v", err) } externalIP, err := metadata.Get("instance/network-interfaces/0/access-configs/0/external-ip") if err != nil { return nil, fmt.Errorf("couldn't get external IP: %v", err) } addresses := []v1.NodeAddress{ {Type: v1.NodeInternalIP, Address: internalIP}, {Type: v1.NodeExternalIP, Address: externalIP}, } if internalDNSFull, err := metadata.Get("instance/hostname"); err != nil { klog.Warningf("couldn't get full internal DNS name: %v", err) } else { addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalDNS, Address: internalDNSFull}, v1.NodeAddress{Type: v1.NodeHostName, Address: internalDNSFull}, ) } return addresses, nil } </ins> } <del> externalIP, err := metadata.Get("instance/network-interfaces/0/access-configs/0/external-ip") </del> <ins> // Use GCE API instanceObj, err := g.getInstanceByName(instanceName) </ins> if err != nil { <del> return nil, fmt.Errorf("couldn't get external IP: %v", err) } addresses := []v1.NodeAddress{ {Type: v1.NodeInternalIP, Address: internalIP}, {Type: v1.NodeExternalIP, Address: externalIP}, </del> <ins> return nil, fmt.Errorf("couldn't get instance details: %v", err) </ins> } <del> if internalDNSFull, err := metadata.Get("instance/hostname"); err != nil { klog.Warningf("couldn't get full internal DNS name: %v", err) } else { addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalDNS, Address: internalDNSFull}, v1.NodeAddress{Type: v1.NodeHostName, Address: internalDNSFull}, ) </del> <ins> instance, err := g.c.Instances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(instanceObj.Name), instanceObj.Zone)) if err != nil { return []v1.NodeAddress{}, fmt.Errorf("error while querying for instance: %v", err) </ins> } <del> return addresses, nil </del> <ins> return nodeAddressesFromInstance(instance) </ins> } // NodeAddressesByProviderID will not be called from the node that is requesting this ID.


if resp.Url == "" { errorMessage := "URL is not set" <del> klog.Errorf("Exec failed: %s", errorMessage) </del> <ins> klog.Errorf("Attach failed: %s", errorMessage) </ins> return nil, errors.New(errorMessage) } return resp, nil


if resp.Url == "" { errorMessage := "URL is not set" <del> klog.Errorf("Exec failed: %s", errorMessage) </del> <ins> klog.Errorf("PortForward failed: %s", errorMessage) </ins> return nil, errors.New(errorMessage) }


} // InstancesV2 returns an implementation of InstancesV2 for Google Compute Engine. <del> // TODO: implement ONLY for external cloud provider </del> <ins> // Implement ONLY for external cloud provider </ins> func (g *Cloud) InstancesV2() (cloudprovider.InstancesV2, bool) { <del> return nil, false </del> <ins> return g, true </ins> } // Zones returns an implementation of Zones for Google Compute Engine.


return false, cloudprovider.NotImplemented } <ins> // InstanceShutdown returns true if the instance is in safe state to detach volumes func (g *Cloud) InstanceShutdown(ctx context.Context, node *v1.Node) (bool, error) { return false, cloudprovider.NotImplemented } </ins> func nodeAddressesFromInstance(instance *compute.Instance) ([]v1.NodeAddress, error) { if len(instance.NetworkInterfaces) < 1 { return nil, fmt.Errorf("could not find network interfaces for instanceID %q", instance.Id)


return true, nil } <ins> // InstanceExists returns true if the instance with the given provider id still exists and is running. // If false is returned with no error, the instance will be immediately deleted by the cloud controller manager. func (g *Cloud) InstanceExists(ctx context.Context, node *v1.Node) (bool, error) { providerID := node.Spec.ProviderID if providerID == "" { var err error if providerID, err = g.InstanceID(ctx, types.NodeName(node.Name)); err != nil { return false, err } } return g.InstanceExistsByProviderID(ctx, providerID) } // InstanceMetadata returns metadata of the specified instance. func (g *Cloud) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) { timeoutCtx, cancel := context.WithTimeout(ctx, 1*time.Hour) defer cancel() providerID := node.Spec.ProviderID if providerID == "" { var err error if providerID, err = g.InstanceID(ctx, types.NodeName(node.Name)); err != nil { return nil, err } } _, zone, name, err := splitProviderID(providerID) if err != nil { return nil, err } region, err := GetGCERegion(zone) if err != nil { return nil, err } instance, err := g.c.Instances().Get(timeoutCtx, meta.ZonalKey(canonicalizeInstanceName(name), zone)) if err != nil { return nil, fmt.Errorf("error while querying for providerID %q: %v", providerID, err) } addresses, err := nodeAddressesFromInstance(instance) if err != nil { return nil, err } return &cloudprovider.InstanceMetadata{ ProviderID:    providerID, InstanceType:  lastComponent(instance.MachineType), NodeAddresses: addresses, Zone:          zone, Region:        region, }, nil } </ins> // InstanceID returns the cloud provider ID of the node with the specified NodeName. func (g *Cloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) { instanceName := mapNodeNameToInstanceName(nodeName)


software-properties-common  lsb-release <del> # focal repo for docker is not yet available, so we use bonic for now # https://github.com/kubernetes/kubernetes/issues/90709 </del> release=$(lsb_release -cs) <del> if [ "$release" == "focal" ]; then release="bionic"; fi </del> # Add the Docker apt-repository curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg


software-properties-common  lsb-release <del> # focal repo for docker is not yet available, so we use bonic for now # https://github.com/kubernetes/kubernetes/issues/90709 </del> release=$(lsb_release -cs) <del> if [ "$release" == "focal" ]; then release="bionic"; fi </del> # Add the Docker apt-repository (as we install containerd from there) curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg


// checkExternalServiceReachability ensures service of type externalName resolves to IP address and no fake externalName is set // FQDN of kubernetes is used as externalName(for air tight platforms). func (j *TestJig) checkExternalServiceReachability(svc *v1.Service, pod *v1.Pod) error { <ins> // NOTE(claudiub): Windows does not support PQDN. svcName := fmt.Sprintf("%s.%s.svc.%s", svc.Name, svc.Namespace, framework.TestContext.ClusterDNSDomain) </ins> // Service must resolve to IP <del> cmd := fmt.Sprintf("nslookup %s", svc.Name) _, err := framework.RunHostCmd(pod.Namespace, pod.Name, cmd) if err != nil { </del> <ins> cmd := fmt.Sprintf("nslookup %s", svcName) _, stderr, err := framework.RunHostCmdWithFullOutput(pod.Namespace, pod.Name, cmd) // NOTE(claudiub): nslookup may return 0 on Windows, even though the DNS name was not found. In this case, // we can check stderr for the error. if err != nil || (framework.NodeOSDistroIs("windows") && strings.Contains(stderr, fmt.Sprintf("can't find %s", svcName))) { </ins> return fmt.Errorf("ExternalName service %q must resolve to IP", pod.Namespace+"/"+pod.Name) } return nil


// Exec runs the kubectl executable. func (b KubectlBuilder) Exec() (string, error) { <ins> stdout, _, err := b.ExecWithFullOutput() return stdout, err } // ExecWithFullOutput runs the kubectl executable, and returns the stdout and stderr. func (b KubectlBuilder) ExecWithFullOutput() (string, string, error) { </ins> var stdout, stderr bytes.Buffer cmd := b.cmd cmd.Stdout, cmd.Stderr = &stdout, &stderr Logf("Running '%s %s'", cmd.Path, strings.Join(cmd.Args[1:], " ")) // skip arg[0] as it is printed separately if err := cmd.Start(); err != nil { <del> return "", fmt.Errorf("error starting %v:nCommand stdout:n%vnstderr:n%vnerror:n%v", cmd, cmd.Stdout, cmd.Stderr, err) </del> <ins> return "", "", fmt.Errorf("error starting %v:nCommand stdout:n%vnstderr:n%vnerror:n%v", cmd, cmd.Stdout, cmd.Stderr, err) </ins> } errCh := make(chan error, 1) go func() {


rc = int(ee.Sys().(syscall.WaitStatus).ExitStatus()) Logf("rc: %d", rc) } <del> return stdout.String(), uexec.CodeExitError{ </del> <ins> return stdout.String(), stderr.String(), uexec.CodeExitError{ </ins> Err:  fmt.Errorf("error running %v:nCommand stdout:n%vnstderr:n%vnerror:n%v", cmd, cmd.Stdout, cmd.Stderr, err), Code: rc, } } case <-b.timeout: b.cmd.Process.Kill() <del> return "", fmt.Errorf("timed out waiting for command %v:nCommand stdout:n%vnstderr:n%v", cmd, cmd.Stdout, cmd.Stderr) </del> <ins> return "", "", fmt.Errorf("timed out waiting for command %v:nCommand stdout:n%vnstderr:n%v", cmd, cmd.Stdout, cmd.Stderr) </ins> } Logf("stderr: %q", stderr.String()) Logf("stdout: %q", stdout.String()) <del> return stdout.String(), nil </del> <ins> return stdout.String(), stderr.String(), nil </ins> } // RunKubectlOrDie is a convenience wrapper over kubectlBuilder


return NewKubectlCommand(namespace, args...).Exec() } <ins> // RunKubectlWithFullOutput is a convenience wrapper over kubectlBuilder // It will also return the command's stderr. func RunKubectlWithFullOutput(namespace string, args ...string) (string, string, error) { return NewKubectlCommand(namespace, args...).ExecWithFullOutput() } </ins> // RunKubectlOrDieInput is a convenience wrapper over kubectlBuilder that takes input to stdin func RunKubectlOrDieInput(namespace string, data string, args ...string) string { return NewKubectlCommand(namespace, args...).WithStdinData(data).ExecOrDie(namespace)


return RunKubectl(ns, "exec", fmt.Sprintf("--namespace=%v", ns), name, "--", "/bin/sh", "-x", "-c", cmd) } <ins> // RunHostCmdWithFullOutput runs the given cmd in the context of the given pod using `kubectl exec` // inside of a shell. It will also return the command's stderr. func RunHostCmdWithFullOutput(ns, name, cmd string) (string, string, error) { return RunKubectlWithFullOutput(ns, "exec", fmt.Sprintf("--namespace=%v", ns), name, "--", "/bin/sh", "-x", "-c", cmd) } </ins> // RunHostCmdOrDie calls RunHostCmd and dies on error. func RunHostCmdOrDie(ns, name, cmd string) string { stdout, err := RunHostCmd(ns, name, cmd)


parameters[k] = v.(string) } } <ins> if snapshotProvider, ok := snapshotClass.Object["driver"]; ok { snapshotter = snapshotProvider.(string) } </ins> case d.SnapshotClass.FromFile != "": snapshotClass, err := loadSnapshotClass(d.SnapshotClass.FromFile) framework.ExpectNoError(err, "load snapshot class from %s", d.SnapshotClass.FromFile)


parameters[k] = v.(string) } } <ins> if snapshotProvider, ok := snapshotClass.Object["driver"]; ok { snapshotter = snapshotProvider.(string) } </ins> } return testsuites.GetSnapshotClass(snapshotter, parameters, ns, suffix)


"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" utilfeature "k8s.io/apiserver/pkg/util/feature" <ins> "k8s.io/client-go/dynamic" </ins> clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"


} return false } <ins> // WatchEventSequenceVerifier ... // manages a watch for a given resource, ensures that events take place in a given order, retries the test on failure //   testContext         cancelation signal across API boundries, e.g: context.TODO() //   dc                  sets up a client to the API //   resourceType        specify the type of resource //   namespace           select a namespace //   resourceName        the name of the given resource //   listOptions         options used to find the resource, recommended to use listOptions.labelSelector //   expectedWatchEvents array of events which are expected to occur //   scenario            the function to run func WatchEventSequenceVerifier(testContext context.Context, dc dynamic.Interface, resourceType schema.GroupVersionResource, namespace string, resourceName string, listOptions metav1.ListOptions, expectedWatchEvents []watch.Event, scenario func(*watchtools.RetryWatcher) []watch.Event) { listWatcher := &cache.ListWatch{ WatchFunc: func(listOptions metav1.ListOptions) (watch.Interface, error) { return dc.Resource(resourceType).Namespace(namespace).Watch(testContext, listOptions) }, } resourceWatch, err := watchtools.NewRetryWatcher("1", listWatcher) ExpectNoError(err, "Failed to create a resource watch of %v in namespace %v", resourceType.Resource, namespace) // NOTE value of 3 retries seems to make sense retries := 3 retriesLoop: for try := 1; try <= retries; try++ { // NOTE the test may need access to the events to see what's going on, such as a change in status actualWatchEvents := scenario(resourceWatch) errs := sets.NewString() // watchEventsLoop: totalValidWatchEvents := 0 actualWatchEventsHasDelete := false for watchEventIndex := range expectedWatchEvents { foundExpectedWatchEvent := false ExpectEqual(len(expectedWatchEvents) <= len(actualWatchEvents), true, "Error: actual watch events amount must be greater than or equal to expected watch events amount") for actualWatchEventIndex := range actualWatchEvents { if actualWatchEvents[watchEventIndex].Type == expectedWatchEvents[actualWatchEventIndex].Type { foundExpectedWatchEvent = true } if actualWatchEvents[actualWatchEventIndex].Type == watch.Deleted && actualWatchEventsHasDelete != true { actualWatchEventsHasDelete = true } } if foundExpectedWatchEvent == false { errs.Insert(fmt.Sprintf("Watch event %v not found", expectedWatchEvents[watchEventIndex].Type)) } totalValidWatchEvents++ } if actualWatchEventsHasDelete == false { _ = dc.Resource(resourceType).Namespace(namespace).DeleteCollection(testContext, metav1.DeleteOptions{}, listOptions) } // TODO restructure failures handling if errs.Len() > 0 && try < retries { fmt.Println(fmt.Errorf("invariants violated:n* %s", strings.Join(errs.List(), "n* "))) continue retriesLoop } ExpectEqual(errs.Len() > 0, false, fmt.Errorf("invariants violated:n* %s", strings.Join(errs.List(), "n* "))) ExpectEqual(totalValidWatchEvents, len(expectedWatchEvents), "Error: there must be an equal amount of total valid watch events (%v) and expected watch events (%v)", totalValidWatchEvents, len(expectedWatchEvents)) } } </ins>


namespace quota. The creation MUST fail release: v1.15 file: test/e2e/apps/rc.go <ins> - testname: Replication Controller, lifecycle codename: '[sig-apps] ReplicationController should test the lifecycle of a ReplicationController [Conformance]' description: A Replication Controller (RC) is created, read, patched, and deleted with verification. release: v1.20 file: test/e2e/apps/rc.go </ins> - testname: StatefulSet, Burst Scaling codename: '[sig-apps] StatefulSet [k8s.io] Basic StatefulSet functionality [StatefulSetBasic] Burst scaling should run to completion even with unhealthy pods [Slow] [Conformance]'


testRCReleaseControlledNotMatching(f) }) <del> ginkgo.It("[Flaky] should test the lifecycle of a ReplicationController", func() { </del> <ins> /* Release: v1.20 Testname: Replication Controller, lifecycle Description: A Replication Controller (RC) is created, read, patched, and deleted with verification. */ framework.ConformanceIt("should test the lifecycle of a ReplicationController", func() { </ins> testRcName := "rc-test" testRcNamespace := ns testRcInitialReplicaCount := int32(1)


metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" <ins> "k8s.io/apimachinery/pkg/util/wait" </ins> "k8s.io/kubernetes/test/e2e/framework" <ins> imageutils "k8s.io/kubernetes/test/utils/image" "time" </ins> "github.com/onsi/ginkgo" ) <ins> const ( podTemplateRetryPeriod  = 1 * time.Second podTemplateRetryTimeout = 1 * time.Minute ) </ins> var _ = ginkgo.Describe("[sig-node] PodTemplates", func() { f := framework.NewDefaultFramework("podtemplate") /*


framework.ExpectNoError(err, "failed to list PodTemplate") framework.ExpectEqual(len(podTemplateList.Items), 0, "PodTemplate list returned items, failed to delete PodTemplate") }) <ins> ginkgo.It("should delete a collection of pod templates", func() { podTemplateNames := []string{"test-podtemplate-1", "test-podtemplate-2", "test-podtemplate-3"} ginkgo.By("Create set of pod templates") // create a set of pod templates in test namespace for _, podTemplateName := range podTemplateNames { _, err := f.ClientSet.CoreV1().PodTemplates(f.Namespace.Name).Create(context.TODO(), &v1.PodTemplate{ ObjectMeta: metav1.ObjectMeta{ Name:   podTemplateName, Labels: map[string]string{"podtemplate-set": "true"}, }, Template: v1.PodTemplateSpec{ Spec: v1.PodSpec{ Containers: []v1.Container{ {Name: "token-test", Image: imageutils.GetE2EImage(imageutils.Agnhost)}, }, }, }, }, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create pod template") framework.Logf("created %v", podTemplateName) } ginkgo.By("get a list of pod templates with a label in the current namespace") // get a list of pod templates podTemplateList, err := f.ClientSet.CoreV1().PodTemplates(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{ LabelSelector: "podtemplate-set=true", }) framework.ExpectNoError(err, "failed to get a list of pod templates") framework.ExpectEqual(len(podTemplateList.Items), len(podTemplateNames), "looking for expected number of pod templates") ginkgo.By("delete collection of pod templates") // delete collection framework.Logf("requesting DeleteCollection of pod templates") err = f.ClientSet.CoreV1().PodTemplates(f.Namespace.Name).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{ LabelSelector: "podtemplate-set=true"}) framework.ExpectNoError(err, "failed to delete all pod templates") ginkgo.By("check that the list of pod templates matches the requested quantity") err = wait.PollImmediate(podTemplateRetryPeriod, podTemplateRetryTimeout, checkPodTemplateListQuantity(f, "podtemplate-set=true", 0)) framework.ExpectNoError(err, "failed to count required pod templates") }) </ins> }) <ins> func checkPodTemplateListQuantity(f *framework.Framework, label string, quantity int) func() (bool, error) { return func() (bool, error) { var err error framework.Logf("requesting list of pod templates to confirm quantity") list, err := f.ClientSet.CoreV1().PodTemplates(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{ LabelSelector: label}) if err != nil { return false, err } if len(list.Items) != quantity { return false, err } return true, nil } } </ins>


visible at runtime in the container. release: v1.9 file: test/e2e/common/downward_api.go <ins> - testname: PodTemplate, delete a collection codename: '[sig-node] PodTemplates should delete a collection of pod templates [Conformance]' description: A set of Pod Templates is created with a label selector which MUST be found when listed. The set of Pod Templates is deleted and MUST NOT show up when listed by its label selector. release: v1.19 file: test/e2e/common/podtemplates.go </ins> - testname: PodTemplate lifecycle codename: '[sig-node] PodTemplates should run the lifecycle of PodTemplates [Conformance]' description: Attempt to create a PodTemplate. Patch the created PodTemplate. Fetching


framework.ExpectEqual(len(podTemplateList.Items), 0, "PodTemplate list returned items, failed to delete PodTemplate") }) <del> ginkgo.It("should delete a collection of pod templates", func() { </del> <ins> /* Release : v1.19 Testname: PodTemplate, delete a collection Description: A set of Pod Templates is created with a label selector which MUST be found when listed. The set of Pod Templates is deleted and MUST NOT show up when listed by its label selector. */ framework.ConformanceIt("should delete a collection of pod templates", func() { </ins> podTemplateNames := []string{"test-podtemplate-1", "test-podtemplate-2", "test-podtemplate-3"} ginkgo.By("Create set of pod templates")


) nodeAuthorizer := node.NewAuthorizer(graph, nodeidentifier.NewDefaultNodeIdentifier(), bootstrappolicy.NodeRules()) authorizers = append(authorizers, nodeAuthorizer) <ins> ruleResolvers = append(ruleResolvers, nodeAuthorizer) </ins> case modes.ModeAlwaysAllow: alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer()


g := NewGraph() g.destinationEdgeThreshold = 3 <del> a := NewAuthorizer(g, nil, nil).(*NodeAuthorizer) </del> <ins> a := NewAuthorizer(g, nil, nil) </ins> addPod := func(podNumber, nodeNumber int) { t.Helper()


rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime/schema" <ins> "k8s.io/apiserver/pkg/authentication/user" </ins> "k8s.io/apiserver/pkg/authorization/authorizer" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/component-base/featuregate"


features featuregate.FeatureGate } <ins> var _ = authorizer.Authorizer(&NodeAuthorizer{}) var _ = authorizer.RuleResolver(&NodeAuthorizer{}) </ins> // NewAuthorizer returns a new node authorizer <del> func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacv1.PolicyRule) authorizer.Authorizer { </del> <ins> func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacv1.PolicyRule) *NodeAuthorizer { </ins> return &NodeAuthorizer{ graph:      graph, identifier: identifier,


csiNodeResource   = storageapi.Resource("csinodes") ) <ins> func (r *NodeAuthorizer) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) { if _, isNode := r.identifier.NodeIdentity(user); isNode { // indicate nodes do not have fully enumerated permissions return nil, nil, true, fmt.Errorf("node authorizer does not support user rule resolution") } return nil, nil, false, nil } </ins> func (r *NodeAuthorizer) Authorize(ctx context.Context, attrs authorizer.Attributes) (authorizer.Decision, string, error) { nodeName, isNode := r.identifier.NodeIdentity(attrs.GetUser()) if !isNode {


populate(g, nodes, pods, pvs, attachments) identifier := nodeidentifier.NewDefaultNodeIdentifier() <del> authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()).(*NodeAuthorizer) </del> <ins> authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()) </ins> node0 := &user.DefaultInfo{Name: "system:node:node0", Groups: []string{"system:nodes"}}