VolumeMounts:  volumeMounts, LivenessProbe: componentProbe(10252, "/healthz"), Resources:     componentResources("200m"), <ins> Env:           getProxyEnvVars(), </ins> }, volumes...), kubeScheduler: componentPod(api.Container{ Name:          kubeScheduler,


Command:       getSchedulerCommand(cfg), LivenessProbe: componentProbe(10251, "/healthz"), Resources:     componentResources("100m"), <ins> Env:           getProxyEnvVars(), </ins> }), }


return } <ins> func getProxyEnvVars() []api.EnvVar { envs := []api.EnvVar{} for _, env := range os.Environ() { pos := strings.Index(env, "=") if pos == -1 { // malformed environment variable, skip it. continue } name := env[:pos] value := env[pos+1:] if strings.HasSuffix(strings.ToLower(name), "_proxy") && value != "" { envVar := api.EnvVar{Name: name, Value: value} envs = append(envs, envVar) } } return envs } </ins>


&HorizontalPodAutoscaler{}, &HorizontalPodAutoscalerList{}, &api.ListOptions{}, <ins> &api.DeleteOptions{}, </ins> ) return nil }


&CronJob{}, &CronJobList{}, &api.ListOptions{}, <ins> &api.DeleteOptions{}, </ins> ) scheme.AddKnownTypeWithName(SchemeGroupVersion.WithKind("ScheduledJob"), &CronJob{}) scheme.AddKnownTypeWithName(SchemeGroupVersion.WithKind("ScheduledJobList"), &CronJobList{})


return } <ins> // truncatePodHostnameIfNeeded truncates the pod hostname if it's longer than 63 chars. func truncatePodHostnameIfNeeded(podName, hostname string) (string, error) { // Cap hostname at 63 chars (specification is 64bytes which is 63 chars and the null terminating char). const hostnameMaxLen = 63 if len(hostname) <= hostnameMaxLen { return hostname, nil } truncated := hostname[:hostnameMaxLen] glog.Errorf("hostname for pod:%q was longer than %d. Truncated hostname to :%q", podName, hostnameMaxLen, truncated) // hostname should not end with '-' or '.' truncated = strings.TrimRight(truncated, "-.") if len(truncated) == 0 { // This should never happen. return "", fmt.Errorf("hostname for pod %q was invalid: %q", podName, hostname) } return truncated, nil } </ins> // GeneratePodHostNameAndDomain creates a hostname and domain name for a pod, // given that pod's spec and annotations or returns an error. func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) { // TODO(vmarmol): Handle better. <del> // Cap hostname at 63 chars (specification is 64bytes which is 63 chars and the null terminating char). </del> clusterDomain := kl.clusterDomain <del> const hostnameMaxLen = 63 </del> podAnnotations := pod.Annotations if podAnnotations == nil { podAnnotations = make(map[string]string)


hostname = hostnameCandidate } } <del> if len(hostname) > hostnameMaxLen { hostname = hostname[:hostnameMaxLen] glog.Errorf("hostname for pod:%q was longer than %d. Truncated hostname to :%q", pod.Name, hostnameMaxLen, hostname) </del> <ins> hostname, err := truncatePodHostnameIfNeeded(pod.Name, hostname) if err != nil { return "", "", err </ins> } hostDomain := ""


} } } <ins> func TestTruncatePodHostname(t *testing.T) { for c, test := range map[string]struct { input  string output string }{ "valid hostname": { input:  "test.pod.hostname", output: "test.pod.hostname", }, "too long hostname": { input:  "1234567.1234567.1234567.1234567.1234567.1234567.1234567.1234567.1234567.", // 8*9=72 chars output: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.1234567",          //8*8-1=63 chars }, "hostname end with .": { input:  "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456.1234567.", // 8*9-1=71 chars output: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456",          //8*8-2=62 chars }, "hostname end with -": { input:  "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456-1234567.", // 8*9-1=71 chars output: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456",          //8*8-2=62 chars }, } { t.Logf("TestCase: %q", c) output, err := truncatePodHostnameIfNeeded("test-pod", test.input) assert.NoError(t, err) assert.Equal(t, test.output, output) } } </ins>


// badGatewayError renders a simple bad gateway error. func badGatewayError(w http.ResponseWriter, req *http.Request) { <ins> w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") </ins> w.WriteHeader(http.StatusBadGateway) fmt.Fprintf(w, "Bad Gateway: %#v", req.RequestURI) }


// forbidden renders a simple forbidden error func forbidden(attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string) { msg := forbiddenMessage(attributes) <ins> w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") </ins> w.WriteHeader(http.StatusForbidden) fmt.Fprintf(w, "%s: %q", msg, reason) }


// internalError renders a simple internal error func internalError(w http.ResponseWriter, req *http.Request, err error) { <ins> w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") </ins> w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Internal Server Error: %#v", req.RequestURI) runtime.HandleError(err)


var ( // TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead. gitMajor     string = "0"              // major version, always numeric <del> gitMinor     string = "4.2+"           // minor version, numeric possibly followed by "+" gitVersion   string = "v0.4.2-dev"     // version from git, output of $(git describe) </del> <ins> gitMinor     string = "4.3+"           // minor version, numeric possibly followed by "+" gitVersion   string = "v0.4.3-dev"     // version from git, output of $(git describe) </ins> gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD) gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty" )


"//test/e2e_node/services:go_default_library", "//test/e2e_node/system:go_default_library", "//test/utils:go_default_library", <ins> "//vendor:github.com/coreos/go-systemd/util", </ins> "//vendor:github.com/davecgh/go-spew/spew", "//vendor:github.com/golang/glog", "//vendor:github.com/kardianos/osext",


"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/stats" "k8s.io/kubernetes/test/e2e/framework" <ins> systemdutil "github.com/coreos/go-systemd/util" </ins> . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gstruct"


"Logs":               BeNil(), "UserDefinedMetrics": BeEmpty(), }) <ins> systemContainers := gstruct.Elements{ "kubelet": sysContExpectations, "runtime": sysContExpectations, } // The Kubelet only manages the 'misc' system container if the host is not running systemd. if !systemdutil.IsRunningSystemd() { framework.Logf("Host not running systemd; expecting 'misc' system container.") systemContainers["misc"] = sysContExpectations } </ins> // Expectations for pods. podExpectations := gstruct.MatchAllFields(gstruct.Fields{ "PodRef":    gstruct.Ignore(),


}) matchExpectations := ptrMatchAllFields(gstruct.Fields{ "Node": gstruct.MatchAllFields(gstruct.Fields{ <del> "NodeName":  Equal(framework.TestContext.NodeName), "StartTime": recent(maxStartAge), "SystemContainers": gstruct.MatchElements(summaryObjectID, gstruct.IgnoreExtras, gstruct.Elements{ "kubelet": sysContExpectations, "runtime": sysContExpectations, }), </del> <ins> "NodeName":         Equal(framework.TestContext.NodeName), "StartTime":        recent(maxStartAge), "SystemContainers": gstruct.MatchAllElements(summaryObjectID, systemContainers), </ins> "CPU": ptrMatchAllFields(gstruct.Fields{ "Time":                 recent(maxStatsAge), "UsageNanoCores":       bounded(100E3, 2E9),


// list all pods to include the pods that don't match the rs`s selector // anymore but has the stale controller ref. // TODO: Do the List and Filter in a single pass, or use an index. <del> pods, err := rsc.podLister.Pods(rs.Namespace).List(labels.Everything()) </del> <ins> allPods, err := rsc.podLister.Pods(rs.Namespace).List(labels.Everything()) </ins> if err != nil { return err } // Ignore inactive pods. var filteredPods []*v1.Pod <del> for _, pod := range pods { </del> <ins> for _, pod := range allPods { </ins> if controller.IsPodActive(pod) { filteredPods = append(filteredPods, pod) }


defer close(stopCh) manager, informers := testNewReplicaSetControllerFromClient(client, stopCh, BurstReplicas) <del> // A controller with 2 replicas and no pods in the store, 2 creates expected </del> <ins> // A controller with 2 replicas and no active pods in the store. // Inactive pods should be ignored. 2 creates expected. </ins> labelMap := map[string]string{"foo": "bar"} rs := newReplicaSet(2, labelMap) informers.Extensions().V1beta1().ReplicaSets().Informer().GetIndexer().Add(rs) <ins> failedPod := newPod("failed-pod", rs, v1.PodFailed, nil, true) deletedPod := newPod("deleted-pod", rs, v1.PodRunning, nil, true) deletedPod.DeletionTimestamp = &metav1.Time{Time: time.Now()} informers.Core().V1().Pods().Informer().GetIndexer().Add(failedPod) informers.Core().V1().Pods().Informer().GetIndexer().Add(deletedPod) </ins> fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl


// list all pods to include the pods that don't match the rc's selector // anymore but has the stale controller ref. // TODO: Do the List and Filter in a single pass, or use an index. <del> pods, err := rm.podLister.Pods(rc.Namespace).List(labels.Everything()) </del> <ins> allPods, err := rm.podLister.Pods(rc.Namespace).List(labels.Everything()) </ins> if err != nil { return err } // Ignore inactive pods. var filteredPods []*v1.Pod <del> for _, pod := range pods { </del> <ins> for _, pod := range allPods { </ins> if controller.IsPodActive(pod) { filteredPods = append(filteredPods, pod) }


cm := controller.NewPodControllerRefManager(rm.podControl, rc, labels.Set(rc.Spec.Selector).AsSelectorPreValidated(), controllerKind) // NOTE: filteredPods are pointing to objects from cache - if you need to // modify them, you need to copy it first. <del> filteredPods, err = cm.ClaimPods(pods) </del> <ins> filteredPods, err = cm.ClaimPods(filteredPods) </ins> if err != nil { return err }


func TestSyncReplicationControllerCreates(t *testing.T) { c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) <del> manager, _, rcInformer := newReplicationManagerFromClient(c, BurstReplicas) </del> <ins> manager, podInformer, rcInformer := newReplicationManagerFromClient(c, BurstReplicas) </ins> <del> // A controller with 2 replicas and no pods in the store, 2 creates expected </del> <ins> // A controller with 2 replicas and no active pods in the store. // Inactive pods should be ignored. 2 creates expected. </ins> rc := newReplicationController(2) rcInformer.Informer().GetIndexer().Add(rc) <ins> failedPod := newPod("failed-pod", rc, v1.PodFailed, nil, true) deletedPod := newPod("deleted-pod", rc, v1.PodRunning, nil, true) deletedPod.DeletionTimestamp = &metav1.Time{Time: time.Now()} podInformer.Informer().GetIndexer().Add(failedPod) podInformer.Informer().GetIndexer().Add(deletedPod) </ins> fakePodControl := controller.FakePodControl{} manager.podControl = &fakePodControl


func (adc *attachDetachController) nodeAdd(obj interface{}) { node, ok := obj.(*v1.Node) <ins> // TODO: investigate if nodeName is empty then if we can return // kubernetes/kubernetes/issues/37777 if node == nil || !ok { return } nodeName := types.NodeName(node.Name) adc.nodeUpdate(nil, obj) // kubernetes/kubernetes/issues/37586 // This is to workaround the case when a node add causes to wipe out // the attached volumes field. This function ensures that we sync with // the actual status. adc.actualStateOfWorld.SetNodeStatusUpdateNeeded(nodeName) } func (adc *attachDetachController) nodeUpdate(oldObj, newObj interface{}) { node, ok := newObj.(*v1.Node) // TODO: investigate if nodeName is empty then if we can return </ins> if node == nil || !ok { return }


// detach controller. Add it to desired state of world. adc.desiredStateOfWorld.AddNode(nodeName) } adc.processVolumesInUse(nodeName, node.Status.VolumesInUse) } <del> func (adc *attachDetachController) nodeUpdate(oldObj, newObj interface{}) { // The flow for update is the same as add. adc.nodeAdd(newObj) } </del> func (adc *attachDetachController) nodeDelete(obj interface{}) { node, ok := obj.(*v1.Node) if node == nil || !ok {


// since volumes should be removed from this list as soon a detach operation // is considered, before the detach operation is triggered). GetVolumesToReportAttached() map[types.NodeName][]v1.AttachedVolume <ins> // GetNodesToUpdateStatusFor returns the map of nodeNames to nodeToUpdateStatusFor GetNodesToUpdateStatusFor() map[types.NodeName]nodeToUpdateStatusFor </ins> } // AttachedVolume represents a volume that is attached to a node.


"Failed to set statusUpdateNeeded to needed %t because nodeName=%q  does not exist", needed, nodeName) <ins> return </ins> } nodeToUpdate.statusUpdateNeeded = needed


return volumesToReportAttached } <ins> func (asw *actualStateOfWorld) GetNodesToUpdateStatusFor() map[types.NodeName]nodeToUpdateStatusFor { return asw.nodesToUpdateStatusFor } </ins> func getAttachedVolume( attachedVolume *attachedVolume, nodeAttachedTo *nodeAttachedTo) AttachedVolume {


verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volumeName), node2Name, devicePath2, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */) } <ins> // Test_SetNodeStatusUpdateNeededError expects the map nodesToUpdateStatusFor // to be empty if the SetNodeStatusUpdateNeeded is called on a node that // does not exist in the actual state of the world func Test_SetNodeStatusUpdateNeededError(t *testing.T) { // Arrange volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t) asw := NewActualStateOfWorld(volumePluginMgr) nodeName := types.NodeName("node-1") // Act asw.SetNodeStatusUpdateNeeded(nodeName) // Assert nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor() if len(nodesToUpdateStatusFor) != 0 { t.Fatalf("nodesToUpdateStatusFor should be empty as nodeName does not exist") } } </ins> func verifyAttachedVolume( t *testing.T, attachedVolumes []AttachedVolume,


} func (nsu *nodeStatusUpdater) UpdateNodeStatuses() error { <ins> // TODO: investigate right behavior if nodeName is empty // kubernetes/kubernetes/issues/37777 </ins> nodesToUpdate := nsu.actualStateOfWorld.GetVolumesToReportAttached() for nodeName, attachedVolumes := range nodesToUpdate { nodeObj, exists, err := nsu.nodeInformer.GetStore().GetByKey(string(nodeName))


e2e_storage_test_environment: '$(echo "$E2E_STORAGE_TEST_ENVIRONMENT" | sed -e "s/'/''/g")' kube_uid: '$(echo "${KUBE_UID}" | sed -e "s/'/''/g")' initial_etcd_cluster: '$(echo "${INITIAL_ETCD_CLUSTER:-}" | sed -e "s/'/''/g")' <del> etcd_quorum_read: '$(echo "${ETCD_QUORUM_READ:-}" | sed -e "s/'/''/g")' </del> hostname: $(hostname -s) enable_default_storage_class: '$(echo "$ENABLE_DEFAULT_STORAGE_CLASS" | sed -e "s/'/''/g")'


etcd_over_ssl: 'false' EOF fi <ins> if [ -n "${ETCD_QUORUM_READ:-}" ]; then cat <<EOF >>/srv/salt-overlay/pillar/cluster-params.sls etcd_quorum_read: '$(echo "${ETCD_QUORUM_READ}" | sed -e "s/'/''/g")' EOF fi </ins> # Configuration changes for test clusters if [ -n "${APISERVER_TEST_ARGS:-}" ]; then cat <<EOF >>/srv/salt-overlay/pillar/cluster-params.sls


e2e_storage_test_environment: '$(echo "$E2E_STORAGE_TEST_ENVIRONMENT" | sed -e "s/'/''/g")' kube_uid: '$(echo "${KUBE_UID}" | sed -e "s/'/''/g")' initial_etcd_cluster: '$(echo "${INITIAL_ETCD_CLUSTER:-}" | sed -e "s/'/''/g")' <del> etcd_quorum_read: '$(echo "${ETCD_QUORUM_READ:-}" | sed -e "s/'/''/g")' </del> hostname: $(hostname -s) EOF


tags = ["automanaged"], deps = [ "//pkg/api:go_default_library", <ins> "//pkg/api/v1:go_default_library", </ins> "//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/kubelet/qos:go_default_library",


"time" "k8s.io/kubernetes/pkg/api" <ins> "k8s.io/kubernetes/pkg/api/v1" </ins> "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" "k8s.io/kubernetes/pkg/kubelet/qos"


KubeAPIBurst      int32 ConfigSyncPeriod  time.Duration CleanupAndExit    bool <del> NodeRef           *api.ObjectReference </del> <ins> NodeRef           *v1.ObjectReference </ins> Master            string Kubeconfig        string }


endpointsConfig.Channel("api"), ) <del> config.NodeRef = &api.ObjectReference{ </del> <ins> config.NodeRef = &v1.ObjectReference{ </ins> Kind:      "Node", Name:      hostname, UID:       types.UID(hostname),


"//cmd/kube-proxy/app/options:go_default_library", "//cmd/kubelet/app:go_default_library", "//pkg/api:go_default_library", <ins> "//pkg/api/v1:go_default_library", </ins> "//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/client/clientset_generated/clientset:go_default_library",


proxyapp "k8s.io/kubernetes/cmd/kube-proxy/app" "k8s.io/kubernetes/cmd/kube-proxy/app/options" "k8s.io/kubernetes/pkg/api" <ins> "k8s.io/kubernetes/pkg/api/v1" </ins> clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/record" proxyconfig "k8s.io/kubernetes/pkg/proxy/config"


config := options.NewProxyConfig() config.OOMScoreAdj = util.Int32Ptr(0) config.ResourceContainer = "" <del> config.NodeRef = &api.ObjectReference{ </del> <ins> config.NodeRef = &v1.ObjectReference{ </ins> Kind:      "Node", Name:      nodeName, UID:       types.UID(nodeName),


docs/man/man1/kubectl-delete.1 docs/man/man1/kubectl-describe.1 docs/man/man1/kubectl-drain.1 <del> docs/man/man1/kubectl-edit-configmap.1 </del> docs/man/man1/kubectl-edit.1 docs/man/man1/kubectl-exec.1 docs/man/man1/kubectl-explain.1


docs/user-guide/kubectl/kubectl_describe.md docs/user-guide/kubectl/kubectl_drain.md docs/user-guide/kubectl/kubectl_edit.md <del> docs/user-guide/kubectl/kubectl_edit_configmap.md </del> docs/user-guide/kubectl/kubectl_exec.md docs/user-guide/kubectl/kubectl_explain.md docs/user-guide/kubectl/kubectl_expose.md


<del> This file is autogenerated, but we've stopped checking such files into the repository to reduce the need for rebases. Please run hack/generate-docs.sh to populate this file. </del>


<del> This file is autogenerated, but we've stopped checking such files into the repository to reduce the need for rebases. Please run hack/generate-docs.sh to populate this file. <!-- BEGIN MUNGE: GENERATED_ANALYTICS --> [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_edit_configmap.md?pixel)]() <!-- END MUNGE: GENERATED_ANALYTICS --> </del>


concurrent-serviceaccount-token-syncs concurrent-service-syncs config-map <del> config-map-data </del> config-map-namespace config-sync-period configure-cloud-routes


"describe.go", "drain.go", "edit.go", <del> "edit_configmap.go", </del> "exec.go", "explain.go", "expose.go",


Long:    editLong, Example: fmt.Sprintf(editExample), Run: func(cmd *cobra.Command, args []string) { <del> args = append([]string{"configmap"}, args...) </del> err := RunEdit(f, out, errOut, cmd, args, options) cmdutil.CheckErr(err) }, ValidArgs:  validArgs, ArgAliases: argAliases, } <del> addEditFlags(cmd, options) cmd.AddCommand(NewCmdEditConfigMap(f, out, errOut)) return cmd } func addEditFlags(cmd *cobra.Command, options *resource.FilenameOptions) { </del> usage := "to use to edit the resource" cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmdutil.AddValidateFlags(cmd)


cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) <ins> return cmd </ins> } func RunEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {


<del> /* Copyright 2016 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cmd import ( "bytes" "fmt" "io" "os" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/apis/meta/v1" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" "k8s.io/kubernetes/pkg/kubectl/resource" ) // NewCmdEditConfigMap is a macro command to edit config maps func NewCmdEditConfigMap(f cmdutil.Factory, cmdOut, errOut io.Writer) *cobra.Command { options := &resource.FilenameOptions{} cmd := &cobra.Command{ Use:     "configmap", Aliases: []string{"cm"}, Short:   "Edit a config map object.", Long:    "Edit and update a config map object", Run: func(cmd *cobra.Command, args []string) { RunEditConfigMap(cmd, f, args, cmdOut, errOut, options) }, } addEditFlags(cmd, options) cmd.Flags().String("config-map-data", "", "If non-empty, specify the name of a data slot in a config map to edit.") return cmd } // RunEditConfigMap runs the edit command for config maps. It either edits the complete map // or it edits individual files inside the config map. func RunEditConfigMap(cmd *cobra.Command, f cmdutil.Factory, args []string, cmdOut, errOut io.Writer, options *resource.FilenameOptions) error { dataFile := cmdutil.GetFlagString(cmd, "config-map-data") if len(dataFile) == 0 { // We need to add the resource type back on to the front args = append([]string{"configmap"}, args...) return RunEdit(f, cmdOut, errOut, cmd, args, options) } cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } cs, err := f.ClientSet() if err != nil { return err } configMap, err := cs.Core().ConfigMaps(cmdNamespace).Get(args[0], v1.GetOptions{}) if err != nil { return err } value, found := configMap.Data[dataFile] if !found { keys := []string{} for key := range configMap.Data { keys = append(keys, key) } return fmt.Errorf("No such data file (%s), filenames are: %vn", dataFile, keys) } edit := editor.NewDefaultEditor(os.Environ()) data, file, err := edit.LaunchTempFile(fmt.Sprintf("%s-edit-", dataFile), "", bytes.NewBuffer([]byte(value))) defer func() { os.Remove(file) }() if err != nil { return err } configMap.Data[dataFile] = string(data) if _, err := cs.Core().ConfigMaps(cmdNamespace).Update(configMap); err != nil { return err } return nil } </del>


return nil, err } if mount.SubPath != "" { <ins> fileinfo, err := os.Lstat(hostPath) if err != nil { return nil, err } perm := fileinfo.Mode() </ins> hostPath = filepath.Join(hostPath, mount.SubPath) <ins> // Create the sub path now because if it's auto-created later when referenced, it may have an // incorrect ownership and mode. For example, the sub path directory must have at least g+rwx // when the pod specifies an fsGroup, and if the directory is not created here, Docker will // later auto-create it with the incorrect mode 0750 if err := os.MkdirAll(hostPath, perm); err != nil { glog.Errorf("failed to mkdir:%s", hostPath) return nil, err } // chmod the sub path because umask may have prevented us from making the sub path with the same // permissions as the mounter path if err := os.Chmod(hostPath, perm); err != nil { return nil, err } </ins> } // Docker Volume Mounts fail on Windows if it is not of the form C:/


//     running on that node. func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *extensions.DaemonSet) (wantToRun, shouldSchedule, shouldContinueRunning bool, err error) { newPod := NewPod(ds, node.Name) <del> critical := utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalCriticalPodAnnotation) && kubelettypes.IsCriticalPod(newPod) </del> // Because these bools require an && of all their required conditions, we start // with all bools set to true and set a bool to false if a condition is not met.


return false, false, false, nil } <del> // TODO: Move it to the predicates for _, c := range node.Status.Conditions { if critical { break } // TODO: There are other node status that the DaemonSet should ideally respect too, //       e.g. MemoryPressure, and DiskPressure if c.Type == v1.NodeOutOfDisk && c.Status == v1.ConditionTrue { // the kubelet will evict this pod if it needs to. Let kubelet // decide whether to continue running this pod so leave shouldContinueRunning // set to true shouldSchedule = false } } </del> reasons, nodeInfo, err := dsc.simulate(newPod, node, ds) if err != nil { glog.Warningf("DaemonSet Predicates failed on node %s for ds '%s/%s' due to unexpected error: %v", node.Name, ds.ObjectMeta.Namespace, ds.ObjectMeta.Name, err)


} var insufficientResourceErr error for _, r := range reasons { glog.V(4).Infof("DaemonSet Predicates failed on node %s for ds '%s/%s' for reason: %v", node.Name, ds.ObjectMeta.Namespace, ds.ObjectMeta.Name, r.GetReason()) switch reason := r.(type) {


var emitEvent bool // we try to partition predicates into two partitions here: intentional on the part of the operator and not. switch reason { <ins> case predicates.ErrNodeOutOfDisk: // the kubelet will evict this pod if it needs to. Let kubelet // decide whether to continue running this pod so leave shouldContinueRunning // set to true shouldSchedule = false </ins> // intentional case predicates.ErrNodeSelectorNotMatch,


if !fit { predicateFails = append(predicateFails, reasons...) } if critical { // If the pod is marked as critical and support for critical pod annotations is enabled, // check predicates for critical pods only. fit, reasons, err = predicates.EssentialPredicates(pod, nil, nodeInfo) } else { fit, reasons, err = predicates.GeneralPredicates(pod, nil, nodeInfo) <ins> ncFit, ncReasons := NodeConditionPredicates(nodeInfo) fit = ncFit && fit reasons = append(reasons, ncReasons...) </ins> } if err != nil { return false, predicateFails, err


return len(predicateFails) == 0, predicateFails, nil } <ins> func NodeConditionPredicates(nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason) { reasons := []algorithm.PredicateFailureReason{} for _, c := range nodeInfo.Node().Status.Conditions { // TODO: There are other node status that the DaemonSet should ideally respect too, //       e.g. MemoryPressure, and DiskPressure if c.Type == v1.NodeOutOfDisk && c.Status == v1.ConditionTrue { reasons = append(reasons, predicates.ErrNodeSelectorNotMatch) break } } return len(reasons) == 0, reasons } </ins> // newControllerRef creates a ControllerRef pointing to the given DaemonSet. func newControllerRef(ds *extensions.DaemonSet) *metav1.OwnerReference { blockOwnerDeletion := true


ErrMaxVolumeCountExceeded    = newPredicateFailureError("MaxVolumeCount") ErrNodeUnderMemoryPressure   = newPredicateFailureError("NodeUnderMemoryPressure") ErrNodeUnderDiskPressure     = newPredicateFailureError("NodeUnderDiskPressure") <ins> ErrNodeOutOfDisk             = newPredicateFailureError("NodeOutOfDisk") </ins> ErrVolumeNodeConflict        = newPredicateFailureError("NoVolumeNodeConflict") // ErrFakePredicate is used for test only. The fake predicates returning false also returns error // as ErrFakePredicate.


// TestListContainers creates several containers and then list them to check // whether the correct metadatas, states, and labels are returned. func TestListContainers(t *testing.T) { <del> ds, _, _ := newTestDockerService() </del> <ins> ds, _, fakeClock := newTestDockerService() </ins> podName, namespace := "foo", "bar" containerName, image := "sidecar", "logger"


expected := []*runtimeapi.Container{} state := runtimeapi.ContainerState_CONTAINER_RUNNING <del> var createdAt int64 = 0 </del> <ins> var createdAt int64 = fakeClock.Now().UnixNano() </ins> for i := range configs { // We don't care about the sandbox id; pass a bogus one. sandboxID := fmt.Sprintf("sandboxid%d", i)


// TestListSandboxes creates several sandboxes and then list them to check // whether the correct metadatas, states, and labels are returned. func TestListSandboxes(t *testing.T) { <del> ds, _, _ := newTestDockerService() </del> <ins> ds, _, fakeClock := newTestDockerService() </ins> name, namespace := "foo", "bar" configs := []*runtimeapi.PodSandboxConfig{} for i := 0; i < 3; i++ {


expected := []*runtimeapi.PodSandbox{} state := runtimeapi.PodSandboxState_SANDBOX_READY <del> var createdAt int64 = 0 </del> <ins> var createdAt int64 = fakeClock.Now().UnixNano() </ins> for i := range configs { id, err := ds.RunPodSandbox(configs[i]) assert.NoError(t, err)


// (kubecontainer) types. const ( statusRunningPrefix = "Up" <ins> statusCreatedPrefix = "Created" </ins> statusExitedPrefix  = "Exited" )


name := "/" + c.Name id := GetFakeContainerID(name) f.appendContainerTrace("Created", id) <ins> timestamp := f.Clock.Now() </ins> // The newest container should be in front, because we assume so in GetPodStatus() f.RunningContainerList = append([]dockertypes.Container{ <del> {ID: id, Names: []string{name}, Image: c.Config.Image, Labels: c.Config.Labels}, </del> <ins> {ID: id, Names: []string{name}, Image: c.Config.Image, Created: timestamp.Unix(), State: statusCreatedPrefix, Labels: c.Config.Labels}, </ins> }, f.RunningContainerList...) f.ContainerMap[id] = convertFakeContainer(&FakeContainer{ <del> ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig, CreatedAt: f.Clock.Now()}) </del> <ins> ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig, CreatedAt: timestamp}) </ins> f.normalSleep(100, 25, 25)


} f.appendContainerTrace("Started", id) container, ok := f.ContainerMap[id] <ins> timestamp := f.Clock.Now() </ins> if !ok { <del> container = convertFakeContainer(&FakeContainer{ID: id, Name: id}) </del> <ins> container = convertFakeContainer(&FakeContainer{ID: id, Name: id, CreatedAt: timestamp}) </ins> } container.State.Running = true container.State.Pid = os.Getpid() <del> container.State.StartedAt = dockerTimestampToString(f.Clock.Now()) </del> <ins> container.State.StartedAt = dockerTimestampToString(timestamp) </ins> container.NetworkSettings.IPAddress = "2.3.4.5" f.ContainerMap[id] = container f.updateContainerStatus(id, statusRunningPrefix)


// print the current object if !isWatchOnly { var objsToPrint []runtime.Object <ins> writer := printers.GetNewTabWriter(out) </ins> if isList { objsToPrint, _ = meta.ExtractList(obj) } else { objsToPrint = append(objsToPrint, obj) } for _, objToPrint := range objsToPrint { <del> if err := printer.PrintObj(objToPrint, out); err != nil { </del> <ins> if err := printer.PrintObj(objToPrint, writer); err != nil { </ins> return fmt.Errorf("unable to output the provided object: %v", err) } } <ins> writer.Flush() </ins> } // print watched changes


"//vendor:github.com/blang/semver", "//vendor:github.com/docker/engine-api/types", "//vendor:github.com/docker/engine-api/types/container", <ins> "//vendor:github.com/docker/go-connections/nat", </ins> "//vendor:github.com/golang/mock/gomock", "//vendor:github.com/stretchr/testify/assert", "//vendor:github.com/stretchr/testify/require",


// Some of this port stuff is under-documented voodoo. // See http://stackoverflow.com/questions/20428302/binding-a-port-to-a-host-interface-using-the-rest-api var protocol string <del> switch strings.ToUpper(string(port.Protocol)) { case "UDP": </del> <ins> switch port.Protocol { case runtimeapi.Protocol_UDP: </ins> protocol = "/udp" <del> case "TCP": </del> <ins> case runtimeapi.Protocol_TCP: </ins> protocol = "/tcp" default: glog.Warningf("Unknown protocol %q: defaulting to TCP", port.Protocol)


"github.com/blang/semver" dockertypes "github.com/docker/engine-api/types" <ins> dockernat "github.com/docker/go-connections/nat" </ins> "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require"


assert.Equal(t, test.err, err != nil) } } <ins> func TestMakePortsAndBindings(t *testing.T) { for desc, test := range map[string]struct { pm           []*runtimeapi.PortMapping exposedPorts map[dockernat.Port]struct{} portmappings map[dockernat.Port][]dockernat.PortBinding }{ "no port mapping": { pm:           nil, exposedPorts: map[dockernat.Port]struct{}{}, portmappings: map[dockernat.Port][]dockernat.PortBinding{}, }, "tcp port mapping": { pm: []*runtimeapi.PortMapping{ { Protocol:      runtimeapi.Protocol_TCP, ContainerPort: 80, HostPort:      80, }, }, exposedPorts: map[dockernat.Port]struct{}{ "80/tcp": {}, }, portmappings: map[dockernat.Port][]dockernat.PortBinding{ "80/tcp": { { HostPort: "80", }, }, }, }, "udp port mapping": { pm: []*runtimeapi.PortMapping{ { Protocol:      runtimeapi.Protocol_UDP, ContainerPort: 80, HostPort:      80, }, }, exposedPorts: map[dockernat.Port]struct{}{ "80/udp": {}, }, portmappings: map[dockernat.Port][]dockernat.PortBinding{ "80/udp": { { HostPort: "80", }, }, }, }, "multipe port mappings": { pm: []*runtimeapi.PortMapping{ { Protocol:      runtimeapi.Protocol_TCP, ContainerPort: 80, HostPort:      80, }, { Protocol:      runtimeapi.Protocol_TCP, ContainerPort: 80, HostPort:      81, }, }, exposedPorts: map[dockernat.Port]struct{}{ "80/tcp": {}, }, portmappings: map[dockernat.Port][]dockernat.PortBinding{ "80/tcp": { { HostPort: "80", }, { HostPort: "81", }, }, }, }, } { t.Logf("TestCase: %s", desc) actualExposedPorts, actualPortMappings := makePortsAndBindings(test.pm) assert.Equal(t, test.exposedPorts, actualExposedPorts) assert.Equal(t, test.portmappings, actualPortMappings) } } </ins>


return c, informers } <del> func (f *fixture) runExpectError(deploymentName string) { f.run_(deploymentName, true) </del> <ins> func (f *fixture) runExpectError(deploymentName string, startInformers bool) { f.run_(deploymentName, startInformers, true) </ins> } func (f *fixture) run(deploymentName string) { <del> f.run_(deploymentName, false) </del> <ins> f.run_(deploymentName, true, false) </ins> } <del> func (f *fixture) run_(deploymentName string, expectError bool) { </del> <ins> func (f *fixture) run_(deploymentName string, startInformers bool, expectError bool) { </ins> c, informers := f.newController() <del> stopCh := make(chan struct{}) defer close(stopCh) informers.Start(stopCh) </del> <ins> if startInformers { stopCh := make(chan struct{}) defer close(stopCh) informers.Start(stopCh) } </ins> err := c.syncDeployment(deploymentName) if !expectError && err != nil {


// Expect to only recheck DeletionTimestamp. f.expectGetDeploymentAction(d) // Sync should fail and requeue to let cache catch up. <del> f.runExpectError(getKey(d, t)) </del> <ins> // Don't start informers, since we don't want cache to catch up for this test. f.runExpectError(getKey(d, t), false) </ins> } // issue: https://github.com/kubernetes/kubernetes/issues/23218


// updateIndices modifies the objects location in the managed indexes, if this is an update, you must provide an oldObj // updateIndices must be called from a function that already has a lock on the cache <del> func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, key string) error { </del> <ins> func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, key string) { </ins> // if we got an old object, we need to remove it before we add it again if oldObj != nil { c.deleteFromIndices(oldObj, key)


for name, indexFunc := range c.indexers { indexValues, err := indexFunc(newObj) if err != nil { <del> return err </del> <ins> panic(fmt.Errorf("unable to calculate an index entry for key %q on index %q: %v", key, name, err)) </ins> } index := c.indices[name] if index == nil {


set.Insert(key) } } <del> return nil </del> } // deleteFromIndices removes the object from each of the managed indexes // it is intended to be called from a function that already has a lock on the cache <del> func (c *threadSafeMap) deleteFromIndices(obj interface{}, key string) error { </del> <ins> func (c *threadSafeMap) deleteFromIndices(obj interface{}, key string) { </ins> for name, indexFunc := range c.indexers { indexValues, err := indexFunc(obj) if err != nil { <del> return err </del> <ins> panic(fmt.Errorf("unable to calculate an index entry for key %q on index %q: %v", key, name, err)) </ins> } index := c.indices[name]


} } } <del> return nil </del> } func (c *threadSafeMap) Resync() error {


kube::test::version::json_object_to_file() { flags=$1 file=$2 <del> kubectl version $flags --output json | sed -e s/'"'/''/g -e s/'}'/''/g -e s/'{'/''/g -e s/'clientVersion:'/'clientVersion:,'/ -e s/'serverVersion:'/'serverVersion:,'/ | tr , 'n' > "${file}" </del> <ins> kubectl version $flags --output json | sed -e s/' '/''/g -e s/'"'/''/g -e s/'}'/''/g -e s/'{'/''/g -e s/'clientVersion:'/'clientVersion:,'/ -e s/'serverVersion:'/'serverVersion:,'/ | tr , 'n' > "${file}" </ins> } kube::test::version::json_client_server_object_to_file() {


} cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).") cmd.Flags().BoolP("short", "", false, "Print just the version number.") <del> cmd.Flags().String("output", "", "one of 'yaml' or 'json'") </del> <ins> cmd.Flags().StringP("output", "o", "", "One of 'yaml' or 'json'.") </ins> cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.") return cmd }


} fmt.Fprintln(out, string(marshalled)) case "json": <del> marshalled, err := json.Marshal(&versionInfo) </del> <ins> marshalled, err := json.MarshalIndent(&versionInfo, "", "  ") </ins> if err != nil { return err }


{"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1} ], <del> "extenders":[ </del> <ins> "extenders" : [ </ins> { "urlPrefix": "http://127.0.0.1:12346/scheduler", "apiVersion": "v1beta1",


"enableHttps": false, "nodeCacheCapable": false } <del> ] </del> <ins> ], "hardPodAffinitySymmetricWeight" : 10 </ins> }


{"name" : "BalancedResourceAllocation", "weight" : 1}, {"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1} <del> ] </del> <ins> ], "hardPodAffinitySymmetricWeight" : 10 </ins> }


fs.IntVar(&s.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", api.DefaultHardPodAffinitySymmetricWeight, "RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+ "to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule.") <ins> fs.MarkDeprecated("hard-pod-affinity-symmetric-weight", "This option was moved to the policy configuration file") </ins> fs.StringVar(&s.FailureDomains, "failure-domains", api.DefaultFailureDomains, "Indicate the "all topologies" set for an empty topologyKey when it's used for PreferredDuringScheduling pod anti-affinity.") fs.MarkDeprecated("failure-domains", "Doesn't have any effect. Will be removed in future version.") leaderelection.BindFlags(&s.LeaderElection, fs)


Priorities []PriorityPolicy // Holds the information to communicate with the extender(s) ExtenderConfigs []ExtenderConfig <ins> // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. // HardPodAffinitySymmetricWeight represents the weight of implicit PreferredDuringScheduling affinity rule, in the range 1-100. HardPodAffinitySymmetricWeight int </ins> } type PredicatePolicy struct {


Priorities []PriorityPolicy `json:"priorities"` // Holds the information to communicate with the extender(s) ExtenderConfigs []ExtenderConfig `json:"extenders"` <ins> // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. // HardPodAffinitySymmetricWeight represents the weight of implicit PreferredDuringScheduling affinity rule, in the range 1-100. HardPodAffinitySymmetricWeight int `json:"hardPodAffinitySymmetricWeight"` </ins> } type PredicatePolicy struct {


} } } <ins> // Providing HardPodAffinitySymmetricWeight in the policy config is the new and preferred way of providing the value. // Give it higher precedence than scheduler CLI configuration when it is provided. if policy.HardPodAffinitySymmetricWeight != 0 { f.hardPodAffinitySymmetricWeight = policy.HardPodAffinitySymmetricWeight } </ins> return f.CreateFromKeys(predicateKeys, priorityKeys, extenders) }


func (f *ConfigFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String, extenders []algorithm.SchedulerExtender) (*scheduler.Config, error) { glog.V(2).Infof("Creating scheduler with fit predicates '%v' and priority functions '%v", predicateKeys, priorityKeys) <del> if f.GetHardPodAffinitySymmetricWeight() < 0 || f.GetHardPodAffinitySymmetricWeight() > 100 { return nil, fmt.Errorf("invalid hardPodAffinitySymmetricWeight: %d, must be in the range 0-100", f.GetHardPodAffinitySymmetricWeight()) </del> <ins> if f.GetHardPodAffinitySymmetricWeight() < 1 || f.GetHardPodAffinitySymmetricWeight() > 100 { return nil, fmt.Errorf("invalid hardPodAffinitySymmetricWeight: %d, must be in the range 1-100", f.GetHardPodAffinitySymmetricWeight()) </ins> } predicateFuncs, err := f.GetPredicates(predicateKeys)


} factory.CreateFromConfig(policy) <ins> hpa := factory.GetHardPodAffinitySymmetricWeight() if hpa != v1.DefaultHardPodAffinitySymmetricWeight { t.Errorf("Wrong hardPodAffinitySymmetricWeight, ecpected: %d, got: %d", v1.DefaultHardPodAffinitySymmetricWeight, hpa) } } func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) { var configData []byte var policy schedulerapi.Policy handler := utiltesting.FakeHandler{ StatusCode:   500, ResponseBody: "", T:            t, } server := httptest.NewServer(&handler) defer server.Close() client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) informerFactory := informers.NewSharedInformerFactory(client, 0) factory := NewConfigFactory( v1.DefaultSchedulerName, client, informerFactory.Core().V1().Nodes(), informerFactory.Core().V1().Pods(), informerFactory.Core().V1().PersistentVolumes(), informerFactory.Core().V1().PersistentVolumeClaims(), informerFactory.Core().V1().ReplicationControllers(), informerFactory.Extensions().V1beta1().ReplicaSets(), informerFactory.Apps().V1beta1().StatefulSets(), informerFactory.Core().V1().Services(), v1.DefaultHardPodAffinitySymmetricWeight, ) // Pre-register some predicate and priority functions RegisterFitPredicate("PredicateOne", PredicateOne) RegisterFitPredicate("PredicateTwo", PredicateTwo) RegisterPriorityFunction("PriorityOne", PriorityOne, 1) RegisterPriorityFunction("PriorityTwo", PriorityTwo, 1) configData = []byte(`{ "kind" : "Policy", "apiVersion" : "v1", "predicates" : [ {"name" : "TestZoneAffinity", "argument" : {"serviceAffinity" : {"labels" : ["zone"]}}}, {"name" : "TestRequireZone", "argument" : {"labelsPresence" : {"labels" : ["zone"], "presence" : true}}}, {"name" : "PredicateOne"}, {"name" : "PredicateTwo"} ], "priorities" : [ {"name" : "RackSpread", "weight" : 3, "argument" : {"serviceAntiAffinity" : {"label" : "rack"}}}, {"name" : "PriorityOne", "weight" : 2}, {"name" : "PriorityTwo", "weight" : 1} ], "hardPodAffinitySymmetricWeight" : 10 }`) if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { t.Errorf("Invalid configuration: %v", err) } factory.CreateFromConfig(policy) hpa := factory.GetHardPodAffinitySymmetricWeight() if hpa != 10 { t.Errorf("Wrong hardPodAffinitySymmetricWeight, ecpected: %d, got: %d", 10, hpa) } </ins> } func TestCreateFromEmptyConfig(t *testing.T) {


apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" <del> "k8s.io/apimachinery/pkg/runtime" </del> <ins> "k8s.io/apimachinery/pkg/runtime/schema" </ins> "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" v1listers "k8s.io/client-go/listers/core/v1"


} } <del> json, err := runtime.Encode(r.codecs.LegacyCodec(), discoveryGroupList) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if _, err := w.Write(json); err != nil { panic(err) } </del> <ins> responsewriters.WriteObjectNegotiated(r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroupList) </ins> } // convertToDiscoveryAPIGroup takes apiservices in a single group and returns a discovery compatible object.


http.Error(w, "", http.StatusNotFound) return } <del> json, err := runtime.Encode(r.codecs.LegacyCodec(), discoveryGroup) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if _, err := w.Write(json); err != nil { panic(err) } </del> <ins> responsewriters.WriteObjectNegotiated(r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroup) </ins> }


go_test( name = "go_default_test", <del> srcs = ["humanreadable_test.go"], </del> <ins> srcs = [ "humanreadable_test.go", "template_test.go", ], </ins> embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library",


package printers import ( <ins> "encoding/base64" </ins> "encoding/json" "fmt" "io"


func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) { t, err := template.New("output"). <del> Funcs(template.FuncMap{"exists": exists}). </del> <ins> Funcs(template.FuncMap{ "exists":       exists, "base64decode": base64decode, }). </ins> Parse(string(tmpl)) if err != nil { return nil, err


} return retErr } <ins> func base64decode(v string) (string, error) { data, err := base64.StdEncoding.DecodeString(v) if err != nil { return "", fmt.Errorf("base64 decode failed: %v", err) } return string(data), nil } </ins>


<ins> /* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package printers import ( "bytes" "strings" "testing" "k8s.io/apimachinery/pkg/runtime" api "k8s.io/kubernetes/pkg/apis/core" ) func TestTemplate(t *testing.T) { testCase := map[string]struct { template  string obj       runtime.Object expectOut string expectErr func(error) (string, bool) }{ "support base64 decoding of secret data": { template: "{{ .Data.username | base64decode }}", obj: &api.Secret{ Data: map[string][]byte{ "username": []byte("hunter"), }, }, expectOut: "hunter", }, "test error path for base64 decoding": { template: "{{ .Data.username | base64decode }}", obj:      &badlyMarshaledSecret{}, expectErr: func(err error) (string, bool) { matched := strings.Contains(err.Error(), "base64 decode") return "a base64 decode error", matched }, }, } for name, test := range testCase { buffer := &bytes.Buffer{} p, err := NewTemplatePrinter([]byte(test.template)) if err != nil { if test.expectErr == nil { t.Errorf("[%s]expected success but got:n %vn", name, err) continue } if expected, ok := test.expectErr(err); !ok { t.Errorf("[%s]expect:n %vn but got:n %vn", name, expected, err) } continue } err = p.PrintObj(test.obj, buffer) if err != nil { if test.expectErr == nil { t.Errorf("[%s]expected success but got:n %vn", name, err) continue } if expected, ok := test.expectErr(err); !ok { t.Errorf("[%s]expect:n %vn but got:n %vn", name, expected, err) } continue } if test.expectErr != nil { t.Errorf("[%s]expect:n errorn but got:n no errorn", name) continue } if test.expectOut != buffer.String() { t.Errorf("[%s]expect:n %vn but got:n %vn", name, test.expectOut, buffer.String()) } } } type badlyMarshaledSecret struct { api.Secret } func (a badlyMarshaledSecret) MarshalJSON() ([]byte, error) { return []byte(`{"apiVersion":"v1","Data":{"username":"--THIS IS NOT BASE64--"},"kind":"Secret"}`), nil } </ins>


labels: app: cockroachdb annotations: <del> scheduler.alpha.kubernetes.io/affinity: > { "podAntiAffinity": { "preferredDuringSchedulingIgnoredDuringExecution": [{ "weight": 100, "labelSelector": { "matchExpressions": [{ "key": "app", "operator": "In", "values": ["cockroachdb"] }] }, "topologyKey": "kubernetes.io/hostname" }] } } </del> # Init containers are run only once in the lifetime of a pod, before # it's started up for the first time. It has to exit successfully # before the pod's main containers are allowed to start.


} ]' spec: <ins> affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpress: - key: app operator: In values: - cockroachdb topologyKey: kubernetes.io/hostname </ins> containers: - name: cockroachdb # Runs the master branch. Not recommended for production, but since


function run-gcloud-compute-with-retries { RETRIES="${RETRIES:-3}" for attempt in $(seq 1 ${RETRIES}); do <del> local -r gcloud_result=$(gcloud compute "$@" 2>&1) local -r ret_val="$?" </del> <ins> # We don't use 'local' to declare gcloud_result as then ret_val always gets value 0. gcloud_result=$(gcloud compute "$@" 2>&1) || local ret_val="$?" </ins> echo "${gcloud_result}" <del> if [[ "${ret_val}" -ne "0" ]]; then </del> <ins> if [[ "${ret_val:-0}" -ne "0" ]]; then </ins> if [[ $(echo "${gcloud_result}" | grep -c "already exists") -gt 0 ]]; then if [[ "${attempt}" == 1 ]]; then echo -e "${color_red}Failed to $1 $2 $3 as the resource hasn't been deleted from a previous run.${color_norm}" >& 2


--disk "name=${MASTER_NAME}-pd,device-name=master-pd,mode=rw,boot=no,auto-delete=no" run-gcloud-compute-with-retries instances add-metadata "${MASTER_NAME}"  <ins> ${GCLOUD_COMMON_ARGS}  </ins> --metadata-from-file startup-script="${KUBE_ROOT}/test/kubemark/resources/start-kubemark-master.sh" if [ "${EVENT_PD:-false}" == "true" ]; then


"//pkg/api/v1/pod:go_default_library", "//pkg/client/clientset_generated/clientset:go_default_library", "//pkg/client/informers/informers_generated/externalversions/core/v1:go_default_library", <ins> "//pkg/client/leaderelection/resourcelock:go_default_library", </ins> "//pkg/client/listers/core/v1:go_default_library", "//pkg/controller:go_default_library", "//pkg/util/metrics:go_default_library",


podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" coreinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions/core/v1" <ins> "k8s.io/kubernetes/pkg/client/leaderelection/resourcelock" </ins> corelisters "k8s.io/kubernetes/pkg/client/listers/core/v1" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/util/metrics"


} for i := range list.Items { ep := &list.Items[i] <ins> if _, ok := ep.Annotations[resourcelock.LeaderElectionRecordAnnotationKey]; ok { // when there are multiple controller-manager instances, // we observe that it will delete leader-election endpoints after 5min // and cause re-election // so skip the delete here // as leader-election only have endpoints without service continue } </ins> key, err := keyFunc(ep) if err != nil { utilruntime.HandleError(fmt.Errorf("Unable to get key for endpoint %#v", ep))


// if the number of consecutive read failure equals or exceeds the failureThreshold , the // configuration is regarded as not ready. failureThreshold int <ins> // number of consecutive failures so far. failures int </ins> // if the configuration is regarded as ready. ready               bool mergedConfiguration runtime.Object


} func (a *poller) Run(stopCh <-chan struct{}) { <del> var failure int go wait.Until(func() { configuration, err := a.get() if err != nil { failure++ if failure >= a.failureThreshold { a.notReady() } return </del> <ins> go wait.Until(a.sync, a.interval, stopCh) } func (a *poller) sync() { configuration, err := a.get() if err != nil { a.failures++ if a.failures >= a.failureThreshold { a.notReady() </ins> } <del> failure = 0 a.setConfigurationAndReady(configuration) }, a.interval, stopCh) </del> <ins> return } a.failures = 0 a.setConfigurationAndReady(configuration) </ins> }


invoked           int successes         int failures          int <del> stopCh            chan struct{} </del> configurationList v1alpha1.InitializerConfigurationList t                 *testing.T }


failures:          failures, successes:         successes, configurationList: configurationList, <del> stopCh:            make(chan struct{}), </del> t:                 t, } } // The first List will be successful; the next m.failures List will <del> // fail; the next m.successes List will be successful; the stopCh is closed at // the 1+m.failures+m.successes call. </del> <ins> // fail; the next m.successes List will be successful // List should only be called 1+m.failures+m.successes times. </ins> func (m *mockLister) List(options metav1.ListOptions) (*v1alpha1.InitializerConfigurationList, error) { m.invoked++ <del> // m.successes could be 0, so call this `if` first. if m.invoked == 1+m.failures+m.successes { close(m.stopCh) } </del> if m.invoked == 1 { return &m.configurationList, nil }


if m.invoked <= 1+m.failures+m.successes { return &m.configurationList, nil } <del> m.t.Fatalf("unexpected call to List, stopCh has been closed at the %d time call", 1+m.successes+m.failures) </del> <ins> m.t.Fatalf("unexpected call to List, should only be called %d times", 1+m.successes+m.failures) </ins> return nil, nil }


mock := newMockLister(c.successes, c.failures, v1alpha1.InitializerConfigurationList{}, t) manager := NewInitializerConfigurationManager(mock) manager.interval = 1 * time.Millisecond <del> manager.Run(mock.stopCh) <-mock.stopCh </del> <ins> for i := 0; i < 1+c.successes+c.failures; i++ { manager.sync() } </ins> _, err := manager.Initializers() if err != nil && c.expectReady { t.Errorf("case %s, expect ready, got: %v", c.name, err)


HOSTNAME_OVERRIDE=${HOSTNAME_OVERRIDE:-"127.0.0.1"} CLOUD_PROVIDER=${CLOUD_PROVIDER:-""} CLOUD_CONFIG=${CLOUD_CONFIG:-""} <del> FEATURE_GATES=${FEATURE_GATES:-"AllAlpha=true"} </del> <ins> FEATURE_GATES=${FEATURE_GATES:-"AllAlpha=false"} </ins> STORAGE_BACKEND=${STORAGE_BACKEND:-"etcd3"} # enable swagger ui ENABLE_SWAGGER_UI=${ENABLE_SWAGGER_UI:-false}


// Build a detailed log of the denial. // Make the whole block conditional so we don't do a lot of string-building we won't use. <del> if glog.V(2) { </del> <ins> if glog.V(5) { </ins> var operation string if requestAttributes.IsResourceRequest() { b := &bytes.Buffer{}


for attempts := 0; attempts < 4; attempts++ { outputBytes, err = exec.Command("gcloud", "compute", "addresses", "create", name, "--project", TestContext.CloudConfig.ProjectID, <del> "--region", region, "-q").CombinedOutput() </del> <ins> "--region", region, "-q", "--format=yaml").CombinedOutput() </ins> if err == nil { break }


# Metadata for driving the build lives here. META_DIR := .make <del> # Our build flags. # TODO(thockin): it would be nice to just use the native flags.  Can we EOL #                these "wrapper" flags? KUBE_GOFLAGS := $(GOFLAGS) KUBE_GOLDFLAGS := $(GOLDFLAGS) KUBE_GOGCFLAGS = $(GOGCFLAGS) </del> <ins> ifdef KUBE_GOFLAGS $(info KUBE_GOFLAGS is now deprecated. Please use GOFLAGS instead.) ifndef GOFLAGS GOFLAGS := $(KUBE_GOFLAGS) unexport KUBE_GOFLAGS else $(error Both KUBE_GOFLAGS and GOFLAGS are set. Please use just GOFLAGS) endif endif </ins> # Extra options for the release or quick-release options: KUBE_RELEASE_RUN_TESTS := $(KUBE_RELEASE_RUN_TESTS)


# Use eval to preserve embedded quoted strings. local goflags goldflags gogcflags <del> eval "goflags=(${KUBE_GOFLAGS:-})" goldflags="${KUBE_GOLDFLAGS:-} $(kube::version::ldflags)" gogcflags="${KUBE_GOGCFLAGS:-}" </del> <ins> eval "goflags=(${GOFLAGS:-})" goldflags="${GOLDFLAGS:-} $(kube::version::ldflags)" gogcflags="${GOGCFLAGS:-}" </ins> local use_go_build local -a targets=()


# KUBE_RACE="-race" make -C "${KUBE_ROOT}" test  WHAT="${WHAT:-$(kube::test::find_integration_test_dirs | paste -sd' ' -)}"  <del> KUBE_GOFLAGS="${KUBE_GOFLAGS:-}"  </del> <ins> GOFLAGS="${GOFLAGS:-}"  </ins> KUBE_TEST_ARGS="${KUBE_TEST_ARGS:-} ${SHORT:--short=true} --vmodule=garbage*collector*=6 --alsologtostderr=true"  KUBE_RACE=""  KUBE_TIMEOUT="${KUBE_TIMEOUT}"


shift $((OPTIND - 1)) # Use eval to preserve embedded quoted strings. <del> eval "goflags=(${KUBE_GOFLAGS:-})" </del> <ins> eval "goflags=(${GOFLAGS:-})" </ins> eval "testargs=(${KUBE_TEST_ARGS:-})" # Used to filter verbose test output.


go install ./cmd/... # Use eval to preserve embedded quoted strings. <del> eval "goflags=(${KUBE_GOFLAGS:-})" </del> <ins> eval "goflags=(${GOFLAGS:-})" </ins> # Filter out arguments that start with "-" and move them to goflags. targets=()


echo '    make test-integration' echo echo "The following invocation will run a specific test with the verbose flag set: " <del> echo '    make test-integration WHAT=./test/integration/pods KUBE_GOFLAGS="-v" KUBE_TEST_ARGS="-run ^TestPodUpdateActiveDeadlineSeconds$"' </del> <ins> echo '    make test-integration WHAT=./test/integration/pods GOFLAGS="-v" KUBE_TEST_ARGS="-run ^TestPodUpdateActiveDeadlineSeconds$"' </ins> echo exit 1


// if container doesn't exist, create one and retry PutPageBlob detail := err.Error() if strings.Contains(detail, errContainerNotFound) { <del> err = blobClient.CreateContainer(vhdContainerName, azs.ContainerAccessTypeContainer) </del> <ins> err = blobClient.CreateContainer(vhdContainerName, azs.ContainerAccessTypePrivate) </ins> if err == nil { err = blobClient.PutPageBlob(vhdContainerName, name, vhdSize, tags) }


// getListener creates a listener on the interface targeted by the given hostname on the given port with // the given protocol. protocol is in net.Listen style which basically admits values like tcp, tcp4, tcp6 func (pf *PortForwarder) getListener(protocol string, hostname string, port *ForwardedPort) (net.Listener, error) { <del> listener, err := net.Listen(protocol, fmt.Sprintf("%s:%d", hostname, port.Local)) </del> <ins> listener, err := net.Listen(protocol, net.JoinHostPort(hostname, strconv.Itoa(int(port.Local)))) </ins> if err != nil { return nil, fmt.Errorf("Unable to create listener: Error %s", err) }


ExpectedListenerAddress: "127.0.0.1", }, { <del> Hostname:                "[::1]", </del> <ins> Hostname:                "::1", </ins> Protocol:                "tcp6", ShouldRaiseError:        false, ExpectedListenerAddress: "::1", }, { <del> Hostname:         "[::1]", </del> <ins> Hostname:         "::1", </ins> Protocol:         "tcp4", ShouldRaiseError: true, },


Protocol:         "tcp6", ShouldRaiseError: true, }, <del> { // IPv6 address must be put into brackets. This test reveals this. Hostname:         "::1", Protocol:         "tcp6", ShouldRaiseError: true, }, </del> } for i, testCase := range testCases {


host, port, _ := net.SplitHostPort(listener.Addr().String()) t.Logf("Asked a %s forward for: %s:%v, got listener %s:%s, expected: %s", testCase.Protocol, testCase.Hostname, 12345, host, port, expectedListenerPort) if host != testCase.ExpectedListenerAddress { <del> t.Errorf("Test case #%d failed: Listener does not listen on exepected address: asked %v got %v", i, testCase.ExpectedListenerAddress, host) </del> <ins> t.Errorf("Test case #%d failed: Listener does not listen on expected address: asked '%v' got '%v'", i, testCase.ExpectedListenerAddress, host) </ins> } if port != expectedListenerPort { t.Errorf("Test case #%d failed: Listener does not listen on exepected port: asked %v got %v", i, expectedListenerPort, port)


fi params+=" --tls-cert-file=/etc/srv/kubernetes/server.cert" params+=" --tls-private-key-file=/etc/srv/kubernetes/server.key" <ins> params+=" --requestheader-client-ca-file=/etc/srv/kubernetes/aggr_ca.crt" params+=" --requestheader-allowed-names=aggregator" params+=" --requestheader-extra-headers-prefix=X-Remote-Extra-" params+=" --requestheader-group-headers=X-Remote-Group" params+=" --requestheader-username-headers=X-Remote-User" params+=" --proxy-client-cert-file=/etc/srv/kubernetes/proxy_client.crt" params+=" --proxy-client-key-file=/etc/srv/kubernetes/proxy_client.key" params+=" --enable-aggregator-routing=true" </ins> params+=" --client-ca-file=/etc/srv/kubernetes/ca.crt" params+=" --token-auth-file=/etc/srv/kubernetes/known_tokens.csv" params+=" --secure-port=443"


sudo bash -c "echo ${CA_CERT_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/ca.crt" &&  sudo bash -c "echo ${MASTER_CERT_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/server.cert" &&  sudo bash -c "echo ${MASTER_KEY_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/server.key" &&  <ins> sudo bash -c "echo ${REQUESTHEADER_CA_CERT_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/aggr_ca.crt" &&  sudo bash -c "echo ${PROXY_CLIENT_CERT_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/proxy_client.crt" &&  sudo bash -c "echo ${PROXY_CLIENT_KEY_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/proxy_client.key" &&  </ins> sudo bash -c "echo ${KUBECFG_CERT_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/kubecfg.crt" &&  sudo bash -c "echo ${KUBECFG_KEY_BASE64} | base64 --decode > /home/kubernetes/k8s_auth_data/kubecfg.key" &&  sudo bash -c "echo "${KUBE_BEARER_TOKEN},admin,admin" > /home/kubernetes/k8s_auth_data/known_tokens.csv" &&


go run ./hack/e2e.go -v -build # Push to GCS <del> yes | ./build/push-ci-build.sh </del> <ins> ./build/push-ci-build.sh </ins> sha256sum _output/release-tars/kubernetes*.tar.gz


for portname := range oldPortsToEndpoints { svcPort := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: oldEndpoints.Namespace, Name: oldEndpoints.Name}, Port: portname} if _, exists := registeredEndpoints[svcPort]; !exists { <ins> lb.resetService(svcPort) } } } func (lb *LoadBalancerRR) resetService(svcPort proxy.ServicePortName) { // If the service is still around, reset but don't delete. if state, ok := lb.services[svcPort]; ok { if len(state.endpoints) > 0 { </ins> glog.V(2).Infof("LoadBalancerRR: Removing endpoints for %s", svcPort) <del> // Reset but don't delete. state := lb.services[svcPort] </del> state.endpoints = []string{} <del> state.index = 0 state.affinity.affinityMap = map[string]*affinityState{} </del> } <ins> state.index = 0 state.affinity.affinityMap = map[string]*affinityState{} </ins> } }


for portname := range portsToEndpoints { svcPort := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}, Port: portname} <del> glog.V(2).Infof("LoadBalancerRR: Removing endpoints for %s", svcPort) // If the service is still around, reset but don't delete. if state, ok := lb.services[svcPort]; ok { state.endpoints = []string{} state.index = 0 state.affinity.affinityMap = map[string]*affinityState{} } </del> <ins> lb.resetService(svcPort) </ins> } }


DockerEndpoint:            dockerEndpoint, DockershimRootDirectory:   "/var/lib/dockershim", DockerExecHandlerName:     "native", <ins> DockerDisableSharedPID:    true, </ins> PodSandboxImage:           defaultPodSandboxImage, ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute}, RktAPIEndpoint:            defaultRktAPIServiceEndpoint,


It("processes in different containers of the same pod should be able to see each other", func() { // TODO(yguo0905): Change this test to run unless the runtime is // Docker and its version is <1.13. <del> By("Check whether shared PID namespace is enabled.") isEnabled, err := isSharedPIDNamespaceEnabled() </del> <ins> By("Check whether shared PID namespace is supported.") isEnabled, err := isSharedPIDNamespaceSupported() </ins> framework.ExpectNoError(err) if !isEnabled { <del> framework.Skipf("Skipped because shared PID namespace is not enabled.") </del> <ins> framework.Skipf("Skipped because shared PID namespace is not supported by this docker version.") </ins> } By("Create a pod with two containers.")


return semver.MustParse(version.APIVersion + ".0"), nil } <del> // isSharedPIDNamespaceEnabled returns true if the Docker version is 1.13.1+ </del> <ins> // isSharedPIDNamespaceSupported returns true if the Docker version is 1.13.1+ </ins> // (API version 1.26+), and false otherwise. <del> func isSharedPIDNamespaceEnabled() (bool, error) { </del> <ins> func isSharedPIDNamespaceSupported() (bool, error) { </ins> version, err := getDockerAPIVersion() if err != nil { return false, err


"--serialize-image-pulls", "false", "--pod-manifest-path", manifestPath, "--file-check-frequency", "10s", // Check file frequently so tests won't wait too long <ins> "--docker-disable-shared-pid=false", </ins> // Assign a fixed CIDR to the node because there is no node controller. // // Note: this MUST be in sync with with the IP in


{Type: v1.NodeMemoryPressure, Status: v1.ConditionFalse}, {Type: v1.NodeDiskPressure, Status: v1.ConditionFalse}, {Type: v1.NodeNetworkUnavailable, Status: v1.ConditionFalse}, <del> {Type: v1.NodeInodePressure, Status: v1.ConditionFalse}, </del> } return node }(),


node := newNode("node1", nil) node.Status.Conditions = []v1.NodeCondition{ {Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}, <del> {Type: v1.NodeInodePressure, Status: v1.ConditionFalse}, </del> } return node }(),


NodeDiskPressure NodeConditionType = "DiskPressure" // NodeNetworkUnavailable means that network for the node is not correctly configured. NodeNetworkUnavailable NodeConditionType = "NetworkUnavailable" <del> // NodeInodePressure means the kubelet is under pressure due to insufficient available inodes. NodeInodePressure NodeConditionType = "InodePressure" </del> ) // NodeCondition contains condition information for a node.


v1.NodeOutOfDisk, v1.NodeMemoryPressure, v1.NodeDiskPressure, <del> // We don't change 'NodeInodePressure' condition, as it'll be removed in future. // v1.NodeInodePressure, </del> // We don't change 'NodeNetworkUnavailable' condition, as it's managed on a control plane level. // v1.NodeNetworkUnavailable, }


if realPath != "" { // Only create the symlink when container log path is specified and log file exists. <ins> // Delete possibly existing file first if err = ds.os.Remove(path); err == nil { glog.Warningf("Deleted previously existing symlink file: %q", path) } </ins> if err = ds.os.Symlink(realPath, path); err != nil { return fmt.Errorf("failed to create symbolic link %q to the container log file %q for container %q: %v", path, realPath, containerID, err)


assert.NoError(t, err) // Verify container log symlink deletion <ins> // symlink is also tentatively deleted at startup </ins> err = ds.RemoveContainer(id) assert.NoError(t, err) <del> assert.Equal(t, fakeOS.Removes, []string{kubeletContainerLogPath}) </del> <ins> assert.Equal(t, []string{kubeletContainerLogPath, kubeletContainerLogPath}, fakeOS.Removes) </ins> } // TestContainerCreationConflict tests the logic to work around docker container


if strings.Contains(cfg.Global.NetworkName, "/") { networkURL = cfg.Global.NetworkName } else { <del> networkURL = gceNetworkURL(apiEndpoint, projectID, networkName) </del> <ins> networkURL = gceNetworkURL(apiEndpoint, projectID, cfg.Global.NetworkName) </ins> } }


gce := &GCECloud{ service:                  service, <ins> serviceAlpha:             serviceAlpha, </ins> serviceBeta:              serviceBeta, containerService:         containerService, cloudkmsService:          cloudkmsService,


desiredReplicas = scaleUpLimit case hpa.Spec.MinReplicas != nil && desiredReplicas < *hpa.Spec.MinReplicas: // make sure we aren't below our minimum <del> setCondition(hpa, autoscalingv2.ScalingLimited, v1.ConditionTrue, "TooFewReplicas", "the desired replica count was less than the minimum replica count") </del> <ins> var statusMsg string if desiredReplicas == 0 { statusMsg = "the desired replica count was zero" } else { statusMsg = "the desired replica count was less than the minimum replica count" } setCondition(hpa, autoscalingv2.ScalingLimited, v1.ConditionTrue, "TooFewReplicas", statusMsg) </ins> desiredReplicas = *hpa.Spec.MinReplicas case desiredReplicas == 0: //  never scale down to 0, reserved for disabling autoscaling


func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) { if !strings.HasPrefix(namespace, "kube-") { <del> glog.Fatalf(`roles can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace) </del> <ins> glog.Fatalf(`rolebindings can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace) </ins> } existingRoleBindings := namespaceRoleBindings[namespace]


// addTokenSecretReference adds a reference to the ServiceAccountToken that will be created func addTokenSecretReference(refs []v1.ObjectReference) []v1.ObjectReference { <del> return addNamedTokenSecretReference(refs, "default-token-p7w9c") </del> <ins> return addNamedTokenSecretReference(refs, "default-token-stdpg") </ins> } // addNamedTokenSecretReference adds a reference to the named ServiceAccountToken


} // createdTokenSecret returns the ServiceAccountToken secret posted when creating a new token secret. <del> // Named "default-token-p7w9c", since that is the first generated name after rand.Seed(1) </del> <ins> // Named "default-token-stdpg", since that is the first generated name after rand.Seed(1) </ins> func createdTokenSecret(overrideName ...string) *v1.Secret { <del> return namedCreatedTokenSecret("default-token-p7w9c") </del> <ins> return namedCreatedTokenSecret("default-token-stdpg") </ins> } // namedTokenSecret returns the ServiceAccountToken secret posted when creating a new token secret with the given name.


// Attempt 2 core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"), <del> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-x50vb")), </del> <ins> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-jk9rt")), </ins> // Attempt 3 core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"), <del> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-scq98")), core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, serviceAccount(addNamedTokenSecretReference(emptySecretReferences(), "default-token-scq98"))), </del> <ins> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-684pg")), core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, serviceAccount(addNamedTokenSecretReference(emptySecretReferences(), "default-token-684pg"))), </ins> }, }, "new serviceaccount with no secrets encountering unending create error": {


core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, createdTokenSecret()), // Retry 1 core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"), <del> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-x50vb")), </del> <ins> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-jk9rt")), </ins> // Retry 2 core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"), <del> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-scq98")), </del> <ins> core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-684pg")), </ins> }, }, "new serviceaccount with missing secrets": {


// We omit vowels from the set of available characters to reduce the chances // of "bad words" being formed. <del> var alphanums = []rune("bcdfghjklmnpqrstvwxz0123456789") </del> <ins> var alphanums = []rune("bcdfghjklmnpqrstvwxz2456789") </ins> // String generates a random alphanumeric string, without vowels, which is n // characters long.  This will panic if n is less than zero.


responses: 200: body: <del> application/json: example: !include examples/pod-list.json </del> <ins> example: !include examples/pod-list.json </ins> post: description: Create a new pod. currentState is ignored if present. body: <del> json/application: schema: !include doc/pod-schema.json example: !include examples/pod.json </del> <ins> schema: !include doc/pod-schema.json example: !include examples/pod.json </ins> /{podId}: get:


responses: 200: body: <del> application/json: example: !include examples/pod.json </del> <ins> example: !include examples/pod.json </ins> put: description: Update a pod body: <del> json/application: schema: !include doc/pod-schema.json example: !include examples/pod.json </del> <ins> schema: !include doc/pod-schema.json example: !include examples/pod.json </ins> delete: description: Delete a specific pod responses: 200: body: <del> application/json: example: | { "success": true } </del> <ins> example: | { "success": true } </ins> /replicationControllers: get:


responses: 200: body: <del> application/json: example: !include examples/controller-list.json </del> <ins> example: !include examples/controller-list.json </ins> post: description: Create a new controller. currentState is ignored if present. body: <del> json/application: schema: !include doc/controller-schema.json example: !include examples/controller.json </del> <ins> schema: !include doc/controller-schema.json example: !include examples/controller.json </ins> /{controllerId}: get:


responses: 200: body: <del> application/json: example: !include examples/controller.json </del> <ins> example: !include examples/controller.json </ins> put: description: Update a controller body: <del> json/application: schema: !include doc/controller-schema.json example: !include examples/controller.json </del> <ins> schema: !include doc/controller-schema.json example: !include examples/controller.json </ins> delete: description: Delete a specific controller responses: 200: body: <del> application/json: example: | { "success": true } </del> <ins> example: | { "success": true } </ins> /services: get:


responses: 200: body: <del> application/json: example: !include examples/service-list.json </del> <ins> example: !include examples/service-list.json </ins> post: description: Create a new service body: <del> json/application: schema: !include doc/service-schema.json example: !include examples/service.json </del> <ins> schema: !include doc/service-schema.json example: !include examples/service.json </ins> /{serviceId}: get:


responses: 200: body: <del> application/json: example: !include examples/service.json </del> <ins> example: !include examples/service.json </ins> put: description: Update a service body: <del> json/application: schema: !include doc/service-schema.json example: !include examples/service.json </del> <ins> schema: !include doc/service-schema.json example: !include examples/service.json </ins> delete: description: Delete a specific service responses: 200: body: <del> application/json: example: | { "success": true } </del> <ins> example: | { "success": true } </ins>


} } <ins> // Set OODCondition for the node. func (kl *Kubelet) setNodeOODCondition(node *v1.Node) { currentTime := metav1.NewTime(kl.clock.Now()) var nodeOODCondition *v1.NodeCondition // Check if NodeOutOfDisk condition already exists and if it does, just pick it up for update. for i := range node.Status.Conditions { if node.Status.Conditions[i].Type == v1.NodeOutOfDisk { nodeOODCondition = &node.Status.Conditions[i] } } newOODCondition := nodeOODCondition == nil if newOODCondition || nodeOODCondition.Status == v1.ConditionUnknown { nodeOODCondition = &v1.NodeCondition{ Type:               v1.NodeOutOfDisk, Status:             v1.ConditionFalse, Reason:             "KubeletHasSufficientDisk", Message:            "kubelet has sufficient disk space available", LastTransitionTime: currentTime, } } // Update the heartbeat time irrespective of all the conditions. nodeOODCondition.LastHeartbeatTime = currentTime if newOODCondition { node.Status.Conditions = append(node.Status.Conditions, *nodeOODCondition) } } </ins> // Maintains Node.Spec.Unschedulable value from previous run of tryUpdateNodeStatus() // TODO: why is this a package var? var oldNodeUnschedulable bool


return []func(*v1.Node) error{ kl.setNodeAddress, withoutError(kl.setNodeStatusInfo), <ins> withoutError(kl.setNodeOODCondition), </ins> withoutError(kl.setNodeMemoryPressureCondition), withoutError(kl.setNodeDiskPressureCondition), withoutError(kl.setNodeReadyCondition),


Status: v1.NodeStatus{ Conditions: []v1.NodeCondition{ { <ins> Type:               v1.NodeOutOfDisk, Status:             v1.ConditionFalse, Reason:             "KubeletHasSufficientDisk", Message:            fmt.Sprintf("kubelet has sufficient disk space available"), LastHeartbeatTime:  metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), LastTransitionTime: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), }, { </ins> Type:               v1.NodeMemoryPressure, Status:             v1.ConditionFalse, Reason:             "KubeletHasSufficientMemory",


Status: v1.NodeStatus{ Conditions: []v1.NodeCondition{ { <ins> Type:               v1.NodeOutOfDisk, Status:             v1.ConditionFalse, Reason:             "KubeletHasSufficientDisk", Message:            fmt.Sprintf("kubelet has sufficient disk space available"), LastHeartbeatTime:  metav1.Time{}, LastTransitionTime: metav1.Time{}, }, { </ins> Type:               v1.NodeMemoryPressure, Status:             v1.ConditionFalse, Reason:             "KubeletHasSufficientMemory",


<ins> FROM debian:jessie RUN apt-get update RUN apt-get -qy install python-seqdiag make curl WORKDIR /diagrams RUN curl -sLo DroidSansMono.ttf https://googlefontdirectory.googlecode.com/hg/apache/droidsansmono/DroidSansMono.ttf ADD . /diagrams CMD bash -c 'make >/dev/stderr && tar cf - *.png' </ins>  No newline at end of file


%.png: %.seqdiag $(FONT) seqdiag --no-transparency -a -f '$(FONT)' $< <ins> # Build the stuff via a docker image .PHONY: docker docker: docker build -t clustering-seqdiag . docker run --rm clustering-seqdiag | tar xvf - docker-clean: docker rmi clustering-seqdiag || true docker images -q --filter "dangling=true" | xargs docker rmi fix-clock-skew: boot2docker ssh sudo date -u -D "%Y%m%d%H%M.%S" --set "$(shell date -u +%Y%m%d%H%M.%S)" </ins>


``` Just call `make` to regenerate the diagrams. <ins> ## Building with Docker If you are on a Mac or your pip install is messed up, you can easily build with docker. ``` make docker ``` The first run will be slow but things should be fast after that. To clean up the docker containers that are created (and other cruft that is left around) you can run `make docker-clean`. If you are using boot2docker and get warnings about clock skew (or if things aren't building for some reason) then you can fix that up with `make fix-clock-skew`. ## Automatically rebuild on file changes If you have the fswatch utility installed, you can have it monitor the file system and automatically rebuild when files have changed.  Just do a `make watch`. </ins>  No newline at end of file


"format": "int32" }, "revisionHistoryLimit": { <del> "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.", </del> <ins> "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.", </ins> "type": "integer", "format": "int32" },


"revisionHistoryLimit": { "type": "integer", "format": "int32", <del> "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2." </del> <ins> "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10." </ins> }, "paused": { "type": "boolean",


revisionHistoryLimit

The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.

The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.

false

integer (int32)


// in extensions. These addons are: // - MaxUnavailable during rolling update set to 25% (1 in extensions) // - MaxSurge value during rolling update set to 25% (1 in extensions) <del> // - RevisionHistoryLimit set to 2 (not set in extensions) </del> <ins> // - RevisionHistoryLimit set to 10 (not set in extensions) </ins> // - ProgressDeadlineSeconds set to 600s (not set in extensions) func SetDefaults_Deployment(obj *appsv1beta2.Deployment) { // Default labels and selector to labels from pod template spec.


} if obj.Spec.RevisionHistoryLimit == nil { obj.Spec.RevisionHistoryLimit = new(int32) <del> *obj.Spec.RevisionHistoryLimit = 2 </del> <ins> *obj.Spec.RevisionHistoryLimit = 10 </ins> } if obj.Spec.ProgressDeadlineSeconds == nil { obj.Spec.ProgressDeadlineSeconds = new(int32)


MaxUnavailable: &defaultIntOrString, }, }, <del> RevisionHistoryLimit:    newInt32(2), </del> <ins> RevisionHistoryLimit:    newInt32(10), </ins> ProgressDeadlineSeconds: newInt32(600), Template:                defaultTemplate, },


// The number of old ReplicaSets to retain to allow rollback. // This is a pointer to distinguish between explicit zero and not specified. <del> // Defaults to 2. </del> <ins> // Defaults to 10. </ins> // +optional optional int32 revisionHistoryLimit = 6;


// The number of old ReplicaSets to retain to allow rollback. // This is a pointer to distinguish between explicit zero and not specified. <del> // Defaults to 2. </del> <ins> // Defaults to 10. </ins> // +optional RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty" protobuf:"varint,6,opt,name=revisionHistoryLimit"`


"template":                "Template describes the pods that will be created.", "strategy":                "The deployment strategy to use to replace existing pods with new ones.", "minReadySeconds":         "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", <del> "revisionHistoryLimit":    "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.", </del> <ins> "revisionHistoryLimit":    "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.", </ins> "paused":                  "Indicates that the deployment is paused.", "rollbackTo":              "The config this deployment is rolling back to. Will be cleared after rollback is done.", "progressDeadlineSeconds": "The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Once autoRollback is implemented, the deployment controller will automatically rollback failed deployments. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.",


podSpecificFieldsSet["spec.nodeName"] = pod.Spec.NodeName podSpecificFieldsSet["spec.restartPolicy"] = string(pod.Spec.RestartPolicy) podSpecificFieldsSet["status.phase"] = string(pod.Status.Phase) <ins> podSpecificFieldsSet["status.podIP"] = string(pod.Status.PodIP) </ins> return generic.AddObjectMetaFieldsSet(podSpecificFieldsSet, &pod.ObjectMeta, true) }


fieldSelector: fields.ParseSelectorOrDie("status.phase=Pending"), expectMatch:   false, }, <ins> { in: &api.Pod{ Status: api.PodStatus{PodIP: "1.2.3.4"}, }, fieldSelector: fields.ParseSelectorOrDie("status.podIP=1.2.3.4"), expectMatch:   true, }, { in: &api.Pod{ Status: api.PodStatus{PodIP: "1.2.3.4"}, }, fieldSelector: fields.ParseSelectorOrDie("status.podIP=4.3.2.1"), expectMatch:   false, }, </ins> } for _, testCase := range testCases { m := MatchPod(labels.Everything(), testCase.fieldSelector)


factory.RegisterFitPredicate("CheckNodeDiskPressure", predicates.CheckNodeDiskPressurePredicate), // Fit is determied by node condtions: not ready, network unavailable and out of disk. <del> factory.RegisterFitPredicate("CheckNodeCondition", predicates.CheckNodeConditionPredicate), </del> factory.RegisterMandatoryFitPredicate("CheckNodeCondition", predicates.CheckNodeConditionPredicate), // Fit is determined by volume zone requirements.


schedulerFactoryMutex sync.Mutex // maps that hold registered algorithm types <del> fitPredicateMap          = make(map[string]FitPredicateFactory) mandatoryFitPredicateMap = make(map[string]FitPredicateFactory) priorityFunctionMap      = make(map[string]PriorityConfigFactory) algorithmProviderMap     = make(map[string]AlgorithmProviderConfig) </del> <ins> fitPredicateMap        = make(map[string]FitPredicateFactory) mandatoryFitPredicates = sets.NewString() priorityFunctionMap    = make(map[string]PriorityConfigFactory) algorithmProviderMap   = make(map[string]AlgorithmProviderConfig) </ins> // Registered metadata producers priorityMetadataProducer  MetadataProducerFactory


schedulerFactoryMutex.Lock() defer schedulerFactoryMutex.Unlock() validateAlgorithmNameOrDie(name) <del> mandatoryFitPredicateMap[name] = func(PluginFactoryArgs) algorithm.FitPredicate { return predicate } </del> <ins> fitPredicateMap[name] = func(PluginFactoryArgs) algorithm.FitPredicate { return predicate } mandatoryFitPredicates.Insert(name) </ins> return name }


predicates[name] = factory(args) } <del> // Always include required fit predicates. for name, factory := range mandatoryFitPredicateMap { if _, found := predicates[name]; !found { </del> <ins> // Always include mandatory fit predicates. for name := range mandatoryFitPredicates { if factory, found := fitPredicateMap[name]; found { </ins> predicates[name] = factory(args) } }


return nil, apierrors.NewBadRequest(fmt.Sprintf("namespace is not allowed on this type: %v", namespace)) } <ins> if len(tokenReview.Spec.Token) == 0 { return nil, apierrors.NewBadRequest(fmt.Sprintf("token is required for TokenReview in authentication")) } </ins> if r.tokenAuthenticator == nil { return tokenReview, nil }


"type": "array", "items": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Initializer" <del> } </del> <ins> }, "x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge" </ins> }, "result": { "description": "If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion.",


library = ":go_default_library", deps = [ "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", <ins> "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", </ins> "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", <ins> "//vendor/k8s.io/apiserver/pkg/admission:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", </ins> ], )


glog.V(5).Infof("Modifying uninitialized resource %s", a.GetResource()) <ins> if updated != nil && len(updated.Pending) == 0 && updated.Result == nil { accessor.SetInitializers(nil) } </ins> // because we are called before validation, we need to ensure the update transition is valid. if errs := validation.ValidateInitializersUpdate(updated, existing, initializerFieldPath); len(errs) > 0 { return errors.NewInvalid(a.GetKind().GroupKind(), a.GetName(), errs)


import ( "reflect" <ins> "strings" </ins> "testing" "k8s.io/api/admissionregistration/v1alpha1" <ins> "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" </ins> "k8s.io/apimachinery/pkg/runtime/schema" <ins> "k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/authorization/authorizer" </ins> ) func newInitializer(name string, rules ...v1alpha1.Rule) *v1alpha1.InitializerConfiguration {


}) } } <ins> type fakeAuthorizer struct { accept bool } func (f *fakeAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) { if f.accept { return true, "", nil } return false, "denied", nil } func TestAdmitUpdate(t *testing.T) { tests := []struct { name             string oldInitializers  *metav1.Initializers newInitializers  *metav1.Initializers verifyUpdatedObj func(runtime.Object) (pass bool, reason string) err              string }{ { name:            "updates on initialized resources are allowed", oldInitializers: nil, newInitializers: nil, err:             "", }, { name:            "updates on initialized resources are allowed", oldInitializers: &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init.k8s.io"}}}, newInitializers: &metav1.Initializers{}, verifyUpdatedObj: func(obj runtime.Object) (bool, string) { accessor, err := meta.Accessor(obj) if err != nil { return false, "cannot get accessor" } if accessor.GetInitializers() != nil { return false, "expect nil initializers" } return true, "" }, err: "", }, { name:            "initializers may not be set once initialized", oldInitializers: nil, newInitializers: &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init.k8s.io"}}}, err:             "field is immutable once initialization has completed", }, } plugin := initializer{ config:     nil, authorizer: &fakeAuthorizer{true}, } for _, tc := range tests { oldObj := &v1.Pod{} oldObj.Initializers = tc.oldInitializers newObj := &v1.Pod{} newObj.Initializers = tc.newInitializers a := admission.NewAttributesRecord(newObj, oldObj, schema.GroupVersionKind{}, "", "foo", schema.GroupVersionResource{}, "", admission.Update, nil) err := plugin.Admit(a) switch { case tc.err == "" && err != nil: t.Errorf("%q: unexpected error: %v", tc.name, err) case tc.err != "" && err == nil: t.Errorf("%q: unexpected no error, expected %s", tc.name, tc.err) case tc.err != "" && err != nil && !strings.Contains(err.Error(), tc.err): t.Errorf("%q: expected %s, got %v", tc.name, tc.err, err) } } } </ins>


} } allErrs = append(allErrs, validateInitializersResult(initializers.Result, fldPath.Child("result"))...) <del> if len(initializers.Pending) == 0 && initializers.Result == nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("pending"), nil, "must be non-empty when result is not set")) } </del> return allErrs }


// When the last pending initializer is removed, and no failing result is set, the initializers // struct will be set to nil and the object is considered as initialized and visible to all // clients. <ins> // +patchMergeKey=name // +patchStrategy=merge </ins> repeated Initializer pending = 1; // If result is set with the Failure field, the object will be persisted to storage and then deleted,


// When the last pending initializer is removed, and no failing result is set, the initializers // struct will be set to nil and the object is considered as initialized and visible to all // clients. <del> Pending []Initializer `json:"pending" protobuf:"bytes,1,rep,name=pending"` </del> <ins> // +patchMergeKey=name // +patchStrategy=merge Pending []Initializer `json:"pending" protobuf:"bytes,1,rep,name=pending" patchStrategy:"merge" patchMergeKey:"name"` </ins> // If result is set with the Failure field, the object will be persisted to storage and then deleted, // ensuring that other clients can observe the deletion. Result *Status `json:"result,omitempty" protobuf:"bytes,2,opt,name=result"`


Expect(err).NotTo(HaveOccurred()) Expect(len(pods.Items)).Should(Equal(1)) }) <ins> It("will be set to nil if a patch removes the last pending initializer", func() { ns := f.Namespace.Name c := f.ClientSet podName := "to-be-patch-initialized-pod" framework.Logf("Creating pod %s", podName) // TODO: lower the timeout so that the server responds faster. _, err := c.CoreV1().Pods(ns).Create(newUninitializedPod(podName)) if err != nil && !errors.IsTimeout(err) { framework.Failf("expect err to be timeout error, got %v", err) } uninitializedPod, err := c.CoreV1().Pods(ns).Get(podName, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) Expect(uninitializedPod.Initializers).NotTo(BeNil()) Expect(len(uninitializedPod.Initializers.Pending)).Should(Equal(1)) patch := fmt.Sprintf(`{"metadata":{"initializers":{"pending":[{"$patch":"delete","name":"%s"}]}}}`, uninitializedPod.Initializers.Pending[0].Name) patchedPod, err := c.CoreV1().Pods(ns).Patch(uninitializedPod.Name, types.StrategicMergePatchType, []byte(patch)) Expect(err).NotTo(HaveOccurred()) Expect(patchedPod.Initializers).To(BeNil()) }) </ins> }) func newUninitializedPod(podName string) *v1.Pod {


}) func cleanTest(f *framework.Framework, block bool) { <ins> // delete the APIService first to avoid causing discovery errors aggrclient := f.AggregatorClient _ = aggrclient.ApiregistrationV1beta1().APIServices().Delete("v1alpha1.wardle.k8s.io", nil) </ins> namespace := "sample-system" client := f.ClientSet _ = client.ExtensionsV1beta1().Deployments(namespace).Delete("sample-apiserver", nil)


_ = client.CoreV1().Namespaces().Delete(namespace, nil) _ = client.RbacV1beta1().ClusterRoles().Delete("wardler", nil) _ = client.RbacV1beta1().ClusterRoleBindings().Delete("wardler:sample-system:anonymous", nil) <del> aggrclient := f.AggregatorClient _ = aggrclient.ApiregistrationV1beta1().APIServices().Delete("v1alpha1.wardle.k8s.io", nil) </del> if block { _ = wait.Poll(100*time.Millisecond, 5*time.Second, func() (bool, error) { _, err := client.CoreV1().Namespaces().Get("sample-system", metav1.GetOptions{})


return numPods, missingTimestamp, nil } <ins> // isDynamicDiscoveryError returns true if the error is a group discovery error // only for groups expected to be created/deleted dynamically during e2e tests func isDynamicDiscoveryError(err error) bool { if !discovery.IsGroupDiscoveryFailedError(err) { return false } discoveryErr := err.(*discovery.ErrGroupDiscoveryFailed) for gv := range discoveryErr.Groups { switch gv.Group { case "mygroup.example.com": // custom_resource_definition // garbage_collector case "wardle.k8s.io": // aggregator default: Logf("discovery error for unexpected group: %#v", gv) return false } } return false } </ins> // hasRemainingContent checks if there is remaining content in the namespace via API discovery func hasRemainingContent(c clientset.Interface, clientPool dynamic.ClientPool, namespace string) (bool, error) { // some tests generate their own framework.Client rather than the default


// find out what content is supported on the server resources, err := c.Discovery().ServerPreferredNamespacedResources() <del> if err != nil { </del> <ins> if err != nil && !isDynamicDiscoveryError(err) { </ins> return false, err } groupVersionResources, err := discovery.GroupVersionResources(resources) <del> if err != nil { </del> <ins> if err != nil && !isDynamicDiscoveryError(err) { </ins> return false, err }


} debugLogThresholdsWithObservation("thresholds - reclaim not satisfied", thresholds, observations) <del> // determine the set of thresholds whose stats have been updated since the last sync thresholds = thresholdsUpdatedStats(thresholds, observations, m.lastObservations) debugLogThresholdsWithObservation("thresholds - updated stats", thresholds, observations) </del> // track when a threshold was first observed now := m.clock.Now() thresholdsFirstObservedAt := thresholdsFirstObservedAt(thresholds, m.thresholdsFirstObservedAt, now)


m.thresholdsFirstObservedAt = thresholdsFirstObservedAt m.nodeConditionsLastObservedAt = nodeConditionsLastObservedAt m.thresholdsMet = thresholds <ins> // determine the set of thresholds whose stats have been updated since the last sync thresholds = thresholdsUpdatedStats(thresholds, observations, m.lastObservations) debugLogThresholdsWithObservation("thresholds - updated stats", thresholds, observations) </ins> m.lastObservations = observations m.Unlock()


color: bfe5bf - name: do-not-merge color: e11d21 <ins> - name: do-not-merge/work-in-progress color: e11d21 - name: do-not-merge/hold color: e11d21 - name: do-not-merge/cherry-pick-not-approved color: e11d21 - name: do-not-merge/release-note-label-needed color: e11d21 - name: do-not-merge/blocked-paths color: e11d21 </ins> - name: flake-has-meta color: fbca04 - name: for-new-contributors


"k8s.io/api/core/v1" "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/kubelet/cadvisor" <ins> kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" </ins> "k8s.io/kubernetes/pkg/util/mount" )


// without needing to be deleted and recreated. if firewallExists { glog.Infof("EnsureLoadBalancer(%v(%v)): updating firewall", loadBalancerName, serviceName) <del> if err := gce.updateFirewall(apiService, makeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil { </del> <ins> if err := gce.updateFirewall(apiService, MakeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil { </ins> return nil, err } glog.Infof("EnsureLoadBalancer(%v(%v)): updated firewall", loadBalancerName, serviceName) } else { glog.Infof("EnsureLoadBalancer(%v(%v)): creating firewall", loadBalancerName, serviceName) <del> if err := gce.createFirewall(apiService, makeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil { </del> <ins> if err := gce.createFirewall(apiService, MakeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil { </ins> return nil, err } glog.Infof("EnsureLoadBalancer(%v(%v)): created firewall", loadBalancerName, serviceName)


// target pool to use local traffic health check. glog.V(2).Infof("Updating from nodes health checks to local traffic health checks for service %v LB %v", apiService.Name, loadBalancerName) if supportsNodesHealthCheck { <del> hcToDelete = makeHttpHealthCheck(makeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort()) </del> <ins> hcToDelete = makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort()) </ins> } tpNeedsUpdate = true }