jiebi/CodeConvo huggingface dataset:
return result, nil } <del> // logPluginScores adds summarized plugin score logging. The goal of this block is to show the highest scoring plugins on // each node, and the average score for those plugins across all nodes. func logPluginScores(nodes []*v1.Node, scoresMap framework.PluginToNodeScores, pod *v1.Pod) { totalPluginScores := make(map[string]int64) for j := range scoresMap { for i := range nodes { totalPluginScores[j] += scoresMap[j][i].Score } } // Build a map of Nodes->PluginScores on that node nodeToPluginScores := make(framework.PluginToNodeScores, len(nodes)) for _, node := range nodes { nodeToPluginScores[node.Name] = make(framework.NodeScoreList, len(scoresMap)) } // Convert the scoresMap (which contains Plugins->NodeScores) to the Nodes->PluginScores map for plugin, nodeScoreList := range scoresMap { for _, nodeScore := range nodeScoreList { klog.V(10).InfoS("Plugin scored node for pod", "pod", klog.KObj(pod), "plugin", plugin, "node", nodeScore.Name, "score", nodeScore.Score) nodeToPluginScores[nodeScore.Name] = append(nodeToPluginScores[nodeScore.Name], framework.NodeScore{Name: plugin, Score: nodeScore.Score}) } } for node, scores := range nodeToPluginScores { // Get the top 3 scoring plugins for each node sort.Slice(scores, func(i, j int) bool { return scores[i].Score > scores[j].Score }) var topScores []pluginScores for _, score := range scores { pluginScore := pluginScores{ Plugin:           score.Name, Score:            score.Score, AverageNodeScore: float64(totalPluginScores[score.Name]) / float64(len(nodes)), } topScores = append(topScores, pluginScore) if len(topScores) == 3 { break } } klog.InfoS("Top 3 plugins for pod on node", "pod", klog.KObj(pod), "node", node, "scores", topScores, ) } } </del> // NewGenericScheduler creates a genericScheduler object. func NewGenericScheduler( cache internalcache.Cache,
// Check that container has restarted ginkgo.By("Waiting for container to restart") restarts := int32(0) <del> err = wait.PollImmediate(10*time.Second, 2*time.Minute, func() (bool, error) { </del> <ins> err = wait.PollImmediate(10*time.Second, framework.PodStartTimeout, func() (bool, error) { </ins> pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(context.TODO(), pod.Name, metav1.GetOptions{}) if err != nil { return false, err
ginkgo.By("Waiting for container to stop restarting") stableCount := int(0) stableThreshold := int(time.Minute / framework.Poll) <del> err = wait.PollImmediate(framework.Poll, 2*time.Minute, func() (bool, error) { </del> <ins> err = wait.PollImmediate(framework.Poll, framework.PodStartTimeout, func() (bool, error) { </ins> pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(context.TODO(), pod.Name, metav1.GetOptions{}) if err != nil { return false, err
var ( // TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead. gitMajor     string = "0"              // major version, always numeric <del> gitMinor     string = "2+"             // minor version, numeric possibly followed by "+" gitVersion   string = "v0.2-dev"       // version from git, output of $(git describe) </del> <ins> gitMinor     string = "3+"             // minor version, numeric possibly followed by "+" gitVersion   string = "v0.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" )
terminationGracePeriodSeconds: 600 hostNetwork: true containers: <del> - image: gcr.io/k8s-ingress-image-push/ingress-gce-glbc-amd64:v1.11.0 </del> <ins> - image: gcr.io/k8s-ingress-image-push/ingress-gce-glbc-amd64:v1.12.0 </ins> livenessProbe: httpGet: path: /healthz
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" <ins> utilnet "k8s.io/apimachinery/pkg/util/net" </ins> utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait"
} kubeClientConfigOverrides(s, clientConfig) <del> closeAllConns, err := updateDialer(clientConfig) if err != nil { return nil, nil, err </del> <ins> // Kubelet needs to be able to recover from stale http connections. // HTTP2 has a mechanism to detect broken connections by sending periodical pings. // HTTP1 only can have one persistent connection, and it will close all Idle connections // once the Kubelet heartbeat fails. However, since there are many edge cases that we can't // control, users can still opt-in to the previous behavior for closing the connections by // setting the environment variable DISABLE_HTTP2. var closeAllConns func() if s := os.Getenv("DISABLE_HTTP2"); len(s) > 0 { klog.InfoS("HTTP2 has been explicitly disabled, updating Kubelet client Dialer to forcefully close active connections on heartbeat failures") closeAllConns, err = updateDialer(clientConfig) if err != nil { return nil, nil, err } } else { closeAllConns = func() { utilnet.CloseIdleConnectionsFor(clientConfig.Transport) } </ins> } return clientConfig, closeAllConns, nil }
} } <ins> // CloseIdleConnectionsFor close idles connections for the Transport. // If the Transport is wrapped it iterates over the wrapped round trippers // until it finds one that implements the CloseIdleConnections method. // If the Transport does not have a CloseIdleConnections method // then this function does nothing. func CloseIdleConnectionsFor(transport http.RoundTripper) { if transport == nil { return } type closeIdler interface { CloseIdleConnections() } switch transport := transport.(type) { case closeIdler: transport.CloseIdleConnections() case RoundTripperWrapper: CloseIdleConnectionsFor(transport.WrappedRoundTripper()) default: klog.Warningf("unknown transport type: %T", transport) } } </ins> type TLSClientConfigHolder interface { TLSClientConfig() *tls.Config }
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" <ins> "k8s.io/apimachinery/pkg/runtime/serializer" </ins> "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/intstr" <ins> utilnet "k8s.io/apimachinery/pkg/util/net" </ins> "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes/scheme" restclientwatch "k8s.io/client-go/rest/watch"
func testRESTClientWithConfig(t testing.TB, srv *httptest.Server, contentConfig ClientContentConfig) *RESTClient { base, _ := url.Parse("http://localhost") <ins> var c *http.Client </ins> if srv != nil { var err error base, err = url.Parse(srv.URL) if err != nil { t.Fatalf("failed to parse test URL: %v", err) } <ins> c = srv.Client() </ins> } versionedAPIPath := defaultResourcePathWithPrefix("", "", "", "") <del> client, err := NewRESTClient(base, versionedAPIPath, contentConfig, nil, nil) </del> <ins> client, err := NewRESTClient(base, versionedAPIPath, contentConfig, nil, c) </ins> if err != nil { t.Fatalf("failed to create a client: %v", err) }
- [Deprecation of PodSecurityPolicy](#deprecation-of-podsecuritypolicy) - [Kubernetes API Reference Documentation](#kubernetes-api-reference-documentation) - [Kustomize Updates in Kubectl](#kustomize-updates-in-kubectl) <del> - [Default Container Labels](#default-container-labels) </del> <ins> - [Default Container Annotation](#default-container-annotation) </ins> - [Immutable Secrets and ConfigMaps](#immutable-secrets-and-configmaps) - [Structured Logging in Kubelet](#structured-logging-in-kubelet) - [Storage Capacity Tracking](#storage-capacity-tracking)
[Kustomize](https://github.com/kubernetes-sigs/kustomize) version in kubectl had a jump from v2.0.3 to [v4.0.5](https://github.com/kubernetes/kubernetes/pull/98946). Kustomize is now treated as a library and future updates will be less sporadic. <del> ### Default Container Labels </del> <ins> ### Default Container Annotation </ins> <del> Pod with multiple containers can use `kubectl.kubernetes.io/default-container` label to have a container preselected for kubectl commands. More can be read in [KEP-2227](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/2227-kubectl-default-container/README.md). </del> <ins> Pod with multiple containers can use `kubectl.kubernetes.io/default-container` annotation to have a container preselected for kubectl commands. More can be read in [KEP-2227](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/2227-kubectl-default-container/README.md). </ins> ### Immutable Secrets and ConfigMaps
Addresses:  []string{"1.2.3.6", "1.2.3.7"}, Conditions: discoveryv1.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, TargetRef:  &corev1.ObjectReference{Kind: "Pod", Name: "test-124"}, <ins> NodeName:   utilpointer.StringPtr("node-2"), </ins> }, }, Ports: []discoveryv1.EndpointPort{
# Windows path it'll use it instead of the default unzipper. # See: https://github.com/containerd/containerd/issues/1896 Add-MachineEnvironmentPath -Path $PIGZ_ROOT <del> # Add process exclusion for Windows Defender to boost performance. </del> <ins> # Add process exclusion for Windows Defender to boost performance. </ins> Add-MpPreference -ExclusionProcess "$PIGZ_ROOTunpigz.exe" Log-Output "Installed Pigz $PIGZ_VERSION" } else {
# TODO(pjh): move the logging agent code below into a separate # module; it was put here temporarily to avoid disrupting the file layout in # the K8s release machinery. <del> $LOGGINGAGENT_VERSION = '1.6.0' </del> <ins> $LOGGINGAGENT_VERSION = '1.7.3' </ins> $LOGGINGAGENT_ROOT = 'C:fluent-bit' $LOGGINGAGENT_SERVICE = 'fluent-bit' $LOGGINGAGENT_CMDLINE = '*fluent-bit.exe*' <del> $LOGGINGEXPORTER_VERSION = 'v0.10.3' </del> <ins> $LOGGINGEXPORTER_VERSION = 'v0.16.2' </ins> $LOGGINGEXPORTER_ROOT = 'C:flb-exporter' $LOGGINGEXPORTER_SERVICE = 'flb-exporter' $LOGGINGEXPORTER_CMDLINE = '*flb-exporter.exe*'
$fluentbit_parser_file = "$LOGGINGAGENT_ROOTconfparsers.conf" $PARSERS_CONFIG | Out-File -FilePath $fluentbit_parser_file -Encoding ASCII <ins> # Create directory for all the log position files. New-Item -Type Directory -Path "/var/run/google-fluentbit/pos-files/" </ins> Log-Output "Wrote logging config to $fluentbit_parser_file" }
# # storage.backlog.mem_limit 5M [INPUT] Name         winlog Interval_Sec 2 # Channels Setup,Windows PowerShell Channels     application,system,security Tag          winevent.raw <del> DB           winlog.sqlite   # </del> <ins> DB           /var/run/google-fluentbit/pos-files/winlog.db </ins> # Json Log Example: # {"log":"[info:2016-02-16T16:04:05.930-08:00] Some log text heren","stream":"stdout","time":"2016-02-17T00:04:05.931087621Z"}
Time_Key    timestamp Time_Format %Y-%m-%dT%H:%M:%S.%L%z <del> # ---------- [PARSER] Name   json Format json Time_Key time Time_Format %d/%b/%Y:%H:%M:%S %z [PARSER] Name         docker Format       json Time_Key     time Time_Format  %Y-%m-%dT%H:%M:%S.%L Time_Keep    On </del> [PARSER] Name        syslog-rfc5424 Format      regex
$PARSERS_CONFIG | Out-File -FilePath $fluentbit_parser_file -Encoding ASCII # Create directory for all the log position files. <del> New-Item -Type Directory -Path "/var/run/google-fluentbit/pos-files/" </del> <ins> New-Item -Type Directory -Path "/var/run/google-fluentbit/pos-files/" -Force | Out-Null </ins> Log-Output "Wrote logging config to $fluentbit_parser_file" }
func updatePod(client clientset.Interface, pod *v1.Pod, condition *v1.PodCondition, nominatedNode string) error { klog.V(3).InfoS("Updating pod condition", "pod", klog.KObj(pod), "conditionType", condition.Type, "conditionStatus", condition.Status, "conditionReason", condition.Reason) <del> podCopy := pod.DeepCopy() </del> <ins> podStatusCopy := pod.Status.DeepCopy() </ins> // NominatedNodeName is updated only if we are trying to set it, and the value is // different from the existing one. <del> if !podutil.UpdatePodCondition(&podCopy.Status, condition) && </del> <ins> if !podutil.UpdatePodCondition(podStatusCopy, condition) && </ins> (len(nominatedNode) == 0 || pod.Status.NominatedNodeName == nominatedNode) { return nil } if nominatedNode != "" { <del> podCopy.Status.NominatedNodeName = nominatedNode </del> <ins> podStatusCopy.NominatedNodeName = nominatedNode </ins> } <del> return util.PatchPod(client, pod, podCopy) </del> <ins> return util.PatchPodStatus(client, pod, podStatusCopy) </ins> } // assume signals to the cache that a pod is already in the cache, so that binding can be asynchronous.
return GetPodStartTime(pod1).Before(GetPodStartTime(pod2)) } <del> // PatchPod calculates the delta bytes change from <old> to <new>, </del> <ins> // PatchPodStatus calculates the delta bytes change from <old.Status> to <newStatus>, </ins> // and then submit a request to API server to patch the pod changes. <del> func PatchPod(cs kubernetes.Interface, old *v1.Pod, new *v1.Pod) error { oldData, err := json.Marshal(old) </del> <ins> func PatchPodStatus(cs kubernetes.Interface, old *v1.Pod, newStatus *v1.PodStatus) error { if newStatus == nil { return nil } oldData, err := json.Marshal(v1.Pod{Status: old.Status}) </ins> if err != nil { return err } <del> newData, err := json.Marshal(new) </del> <ins> newData, err := json.Marshal(v1.Pod{Status: *newStatus}) </ins> if err != nil { return err }
if len(p.Status.NominatedNodeName) == 0 { continue } <del> podCopy := p.DeepCopy() podCopy.Status.NominatedNodeName = "" if err := PatchPod(cs, p, podCopy); err != nil { </del> <ins> podStatusCopy := p.Status.DeepCopy() podStatusCopy.NominatedNodeName = "" if err := PatchPodStatus(cs, p, podStatusCopy); err != nil { </ins> errs = append(errs, err) } }
}) } } <ins> func TestPatchPodStatus(t *testing.T) { tests := []struct { name           string pod            v1.Pod statusToUpdate v1.PodStatus }{ { name: "Should update pod conditions successfully", pod: v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Namespace: "ns", Name:      "pod1", }, Spec: v1.PodSpec{ ImagePullSecrets: []v1.LocalObjectReference{{Name: "foo"}}, }, }, statusToUpdate: v1.PodStatus{ Conditions: []v1.PodCondition{ { Type:   v1.PodScheduled, Status: v1.ConditionFalse, }, }, }, }, { // ref: #101697, #94626 - ImagePullSecrets are allowed to have empty secret names // which would fail the 2-way merge patch generation on Pod patches // due to the mergeKey being the name field name: "Should update pod conditions successfully on a pod Spec with secrets with empty name", pod: v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Namespace: "ns", Name:      "pod2", }, Spec: v1.PodSpec{ // this will serialize to imagePullSecrets:[{}] ImagePullSecrets: make([]v1.LocalObjectReference, 1), }, }, statusToUpdate: v1.PodStatus{ Conditions: []v1.PodCondition{ { Type:   v1.PodScheduled, Status: v1.ConditionFalse, }, }, }, }, } client := clientsetfake.NewSimpleClientset() for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { _, err := client.CoreV1().Pods(tc.pod.Namespace).Create(context.TODO(), &tc.pod, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } err = PatchPodStatus(client, &tc.pod, &tc.statusToUpdate) if err != nil { t.Fatal(err) } retrievedPod, err := client.CoreV1().Pods(tc.pod.Namespace).Get(context.TODO(), tc.pod.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } if diff := cmp.Diff(tc.statusToUpdate, retrievedPod.Status); diff != "" { t.Errorf("unexpected pod status (-want,+got):n%s", diff) } }) } } </ins>
// FieldImmutableErrorMsg is a error message for field is immutable. const FieldImmutableErrorMsg string = `field is immutable` <del> const totalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB </del> <ins> const TotalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB </ins> // BannedOwners is a black list of object that are not allowed to be owners. var BannedOwners = map[schema.GroupVersionKind]struct{}{
// ValidateAnnotations validates that a set of annotations are correctly defined. func ValidateAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} <del> var totalSize int64 for k, v := range annotations { </del> <ins> for k := range annotations { </ins> for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) { allErrs = append(allErrs, field.Invalid(fldPath, k, msg)) } <del> totalSize += (int64)(len(k)) + (int64)(len(v)) </del> } <del> if totalSize > (int64)(totalAnnotationSizeLimitB) { allErrs = append(allErrs, field.TooLong(fldPath, "", totalAnnotationSizeLimitB)) </del> <ins> if err := ValidateAnnotationsSize(annotations); err != nil { allErrs = append(allErrs, field.TooLong(fldPath, "", TotalAnnotationSizeLimitB)) </ins> } return allErrs } <ins> func ValidateAnnotationsSize(annotations map[string]string) error { var totalSize int64 for k, v := range annotations { totalSize += (int64)(len(k)) + (int64)(len(v)) } if totalSize > (int64)(TotalAnnotationSizeLimitB) { return fmt.Errorf("annotations size %d is larger than limit %d", totalSize, TotalAnnotationSizeLimitB) } return nil } </ins> func validateOwnerReference(ownerReference metav1.OwnerReference, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} gvk := schema.FromAPIVersionAndKind(ownerReference.APIVersion, ownerReference.Kind)
{"1234/5678": "bar"}, {"1.2.3.4/5678": "bar"}, {"UpperCase123": "bar"}, <del> {"a": strings.Repeat("b", totalAnnotationSizeLimitB-1)}, </del> <ins> {"a": strings.Repeat("b", TotalAnnotationSizeLimitB-1)}, </ins> { <del> "a": strings.Repeat("b", totalAnnotationSizeLimitB/2-1), "c": strings.Repeat("d", totalAnnotationSizeLimitB/2-1), </del> <ins> "a": strings.Repeat("b", TotalAnnotationSizeLimitB/2-1), "c": strings.Repeat("d", TotalAnnotationSizeLimitB/2-1), </ins> }, } for i := range successCases {
} } totalSizeErrorCases := []map[string]string{ <del> {"a": strings.Repeat("b", totalAnnotationSizeLimitB)}, </del> <ins> {"a": strings.Repeat("b", TotalAnnotationSizeLimitB)}, </ins> { <del> "a": strings.Repeat("b", totalAnnotationSizeLimitB/2), "c": strings.Repeat("d", totalAnnotationSizeLimitB/2), </del> <ins> "a": strings.Repeat("b", TotalAnnotationSizeLimitB/2), "c": strings.Repeat("d", TotalAnnotationSizeLimitB/2), </ins> }, } for i := range totalSizeErrorCases {
corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" <ins> apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation" </ins> "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" ) <del> const totalAnnotationSizeLimitB int64 = 256 * (1 << 10) // 256 kB </del> type lastAppliedUpdater struct { fieldManager Manager }
} return string(lastApplied), nil } <del> func isAnnotationsValid(annotations map[string]string) error { var totalSize int64 for k, v := range annotations { totalSize += (int64)(len(k)) + (int64)(len(v)) } if totalSize > (int64)(totalAnnotationSizeLimitB) { return fmt.Errorf("annotations size %d is larger than limit %d", totalSize, totalAnnotationSizeLimitB) } return nil } </del>
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" <ins> utilrand "k8s.io/apimachinery/pkg/util/rand" </ins> "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" watchtools "k8s.io/client-go/tools/watch" <ins> "k8s.io/client-go/util/retry" </ins> appsinternal "k8s.io/kubernetes/pkg/apis/apps" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" "k8s.io/kubernetes/test/e2e/framework"
MUST succeed. It MUST succeed when deleting the Deployment. release: v1.20 file: test/e2e/apps/deployment.go <ins> - testname: Deployment, status sub-resource codename: '[sig-apps] Deployment should validate Deployment Status endpoints [Conformance]' description: When a Deployment is created it MUST succeed. Attempt to read, update and patch its status sub-resource; all mutating sub-resource operations MUST be visible to subsequent reads. release: v1.22 file: test/e2e/apps/deployment.go </ins> - testname: 'PodDisruptionBudget: list and delete collection' codename: '[sig-apps] DisruptionController Listing PodDisruptionBudgets for all namespaces should list and delete a collection of PodDisruptionBudgets [Conformance]'
framework.ExpectNoError(err, "failed to see %v event", watch.Deleted) }) <del> ginkgo.It("should validate Deployment Status endpoints", func() { </del> <ins> /* Release: v1.22 Testname: Deployment, status sub-resource Description: When a Deployment is created it MUST succeed. Attempt to read, update and patch its status sub-resource; all mutating sub-resource operations MUST be visible to subsequent reads. */ framework.ConformanceIt("should validate Deployment Status endpoints", func() { </ins> dClient := c.AppsV1().Deployments(ns) dName := "test-deployment-" + utilrand.String(5) labelSelector := "e2e=testing"
return false } <del> accessModes := c.spec.PersistentVolume.Spec.AccessModes </del> <ins> if c.spec.PersistentVolume == nil { klog.V(4).Info(log("mounter.SetupAt Warning: skipping fsGroup permission change, no access mode available. The volume may only be accessible to root users.")) return false } </ins> if c.spec.PersistentVolume.Spec.AccessModes == nil { klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, access modes not provided")) return false } <del> if !hasReadWriteOnce(accessModes) { </del> <ins> if !hasReadWriteOnce(c.spec.PersistentVolume.Spec.AccessModes) { </ins> klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, only support ReadWriteOnce access mode")) return false }
authenticationv1 "k8s.io/api/authentication/v1" api "k8s.io/api/core/v1" <ins> corev1 "k8s.io/api/core/v1" </ins> storage "k8s.io/api/storage/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/labels" <del> "k8s.io/apimachinery/pkg/util/diff" </del> "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation"
// PersistentVolumeSource should be immutable after creation. if !apiequality.Semantic.DeepEqual(newPv.Spec.PersistentVolumeSource, oldPv.Spec.PersistentVolumeSource) { <del> pvcSourceDiff := diff.ObjectDiff(newPv.Spec.PersistentVolumeSource, oldPv.Spec.PersistentVolumeSource) </del> <ins> pvcSourceDiff := cmp.Diff(oldPv.Spec.PersistentVolumeSource, newPv.Spec.PersistentVolumeSource) </ins> allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "persistentvolumesource"), fmt.Sprintf("spec.persistentvolumesource is immutable after creationn%v", pvcSourceDiff))) } allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.VolumeMode, oldPv.Spec.VolumeMode, field.NewPath("volumeMode"))...)
statusSize := oldPvc.Status.Capacity["storage"] if !apiequality.Semantic.DeepEqual(newPvcClone.Spec, oldPvcClone.Spec) { <del> specDiff := diff.ObjectDiff(newPvcClone.Spec, oldPvcClone.Spec) </del> <ins> specDiff := cmp.Diff(oldPvcClone.Spec, newPvcClone.Spec) </ins> allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), fmt.Sprintf("spec is immutable after creation except resources.requests for bound claimsn%v", specDiff))) } if newSize.Cmp(oldSize) < 0 {
// changes to Spec are not allowed, but updates to label/and some annotations are OK. // no-op updates pass validation. if !apiequality.Semantic.DeepEqual(newPvcClone.Spec, oldPvcClone.Spec) { <del> specDiff := diff.ObjectDiff(newPvcClone.Spec, oldPvcClone.Spec) </del> <ins> specDiff := cmp.Diff(oldPvcClone.Spec, newPvcClone.Spec) </ins> allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), fmt.Sprintf("field is immutable after creationn%v", specDiff))) } }