Commit 5190ace8 authored by Dawn Chen's avatar Dawn Chen Committed by GitHub

Merge pull request #37343 from ymqytw/revert_branch

Revert list of primitives fix
parents ead3cc8c 3cc294b1
...@@ -591,11 +591,11 @@ func patchResource( ...@@ -591,11 +591,11 @@ func patchResource(
if err != nil { if err != nil {
return nil, err return nil, err
} }
currentPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, currentObjectJS, versionedObj, strategicpatch.SMPatchVersionLatest) currentPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, currentObjectJS, versionedObj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
originalPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, originalPatchedObjJS, versionedObj, strategicpatch.SMPatchVersionLatest) originalPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, originalPatchedObjJS, versionedObj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -213,7 +213,7 @@ func (tc *patchTestCase) Run(t *testing.T) { ...@@ -213,7 +213,7 @@ func (tc *patchTestCase) Run(t *testing.T) {
continue continue
case api.StrategicMergePatchType: case api.StrategicMergePatchType:
patch, err = strategicpatch.CreateStrategicMergePatch(originalObjJS, changedJS, versionedObj, strategicpatch.SMPatchVersionLatest) patch, err = strategicpatch.CreateStrategicMergePatch(originalObjJS, changedJS, versionedObj)
if err != nil { if err != nil {
t.Errorf("%s: unexpected error: %v", tc.name, err) t.Errorf("%s: unexpected error: %v", tc.name, err)
return return
......
...@@ -244,8 +244,7 @@ func (e *eventLogger) eventObserve(newEvent *api.Event) (*api.Event, []byte, err ...@@ -244,8 +244,7 @@ func (e *eventLogger) eventObserve(newEvent *api.Event) (*api.Event, []byte, err
newData, _ := json.Marshal(event) newData, _ := json.Marshal(event)
oldData, _ := json.Marshal(eventCopy2) oldData, _ := json.Marshal(eventCopy2)
// Defaulting to SMPatchVersion_1_5 is safe, since we only update Count and LastTimestamp, and none of them has list of primitives patch, err = strategicpatch.CreateStrategicMergePatch(oldData, newData, event)
patch, err = strategicpatch.CreateStrategicMergePatch(oldData, newData, event, strategicpatch.SMPatchVersion_1_5)
} }
// record our new observation // record our new observation
......
...@@ -107,9 +107,8 @@ func (nsu *nodeStatusUpdater) UpdateNodeStatuses() error { ...@@ -107,9 +107,8 @@ func (nsu *nodeStatusUpdater) UpdateNodeStatuses() error {
err) err)
} }
// Defaulting to SMPatchVersion_1_5 is safe, since updateNodeStatus doesn't update any lists of primitives
patchBytes, err := patchBytes, err :=
strategicpatch.CreateStrategicMergePatch(oldData, newData, node, strategicpatch.SMPatchVersion_1_5) strategicpatch.CreateStrategicMergePatch(oldData, newData, node)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"failed to CreateStrategicMergePatch for node %q. %v", "failed to CreateStrategicMergePatch for node %q. %v",
......
...@@ -191,11 +191,9 @@ go_test( ...@@ -191,11 +191,9 @@ go_test(
"//pkg/runtime/serializer/streaming:go_default_library", "//pkg/runtime/serializer/streaming:go_default_library",
"//pkg/types:go_default_library", "//pkg/types:go_default_library",
"//pkg/util/intstr:go_default_library", "//pkg/util/intstr:go_default_library",
"//pkg/util/strategicpatch:go_default_library",
"//pkg/util/strings:go_default_library", "//pkg/util/strings:go_default_library",
"//pkg/util/term:go_default_library", "//pkg/util/term:go_default_library",
"//pkg/util/wait:go_default_library", "//pkg/util/wait:go_default_library",
"//pkg/version:go_default_library",
"//pkg/watch:go_default_library", "//pkg/watch:go_default_library",
"//pkg/watch/versioned:go_default_library", "//pkg/watch/versioned:go_default_library",
"//vendor:github.com/spf13/cobra", "//vendor:github.com/spf13/cobra",
......
...@@ -239,8 +239,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro ...@@ -239,8 +239,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
if err != nil { if err != nil {
return err return err
} }
// Defaulting to SMPatchVersion_1_5 is safe, since it just update the annotation which is a map[string]string patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj)
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj, strategicpatch.SMPatchVersion_1_5)
createdPatch := err == nil createdPatch := err == nil
if err != nil { if err != nil {
glog.V(2).Infof("couldn't compute patch: %v", err) glog.V(2).Infof("couldn't compute patch: %v", err)
......
...@@ -24,6 +24,8 @@ import ( ...@@ -24,6 +24,8 @@ import (
"testing" "testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/restclient/fake" "k8s.io/kubernetes/pkg/client/restclient/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
...@@ -392,7 +394,7 @@ func TestAnnotateErrors(t *testing.T) { ...@@ -392,7 +394,7 @@ func TestAnnotateErrors(t *testing.T) {
f, tf, _, _ := cmdtesting.NewAPIFactory() f, tf, _, _ := cmdtesting.NewAPIFactory()
tf.Printer = &testPrinter{} tf.Printer = &testPrinter{}
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(f, buf) cmd := NewCmdAnnotate(f, buf)
...@@ -430,12 +432,6 @@ func TestAnnotateObject(t *testing.T) { ...@@ -430,12 +432,6 @@ func TestAnnotateObject(t *testing.T) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/version":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil
default: default:
...@@ -457,7 +453,7 @@ func TestAnnotateObject(t *testing.T) { ...@@ -457,7 +453,7 @@ func TestAnnotateObject(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(f, buf) cmd := NewCmdAnnotate(f, buf)
...@@ -486,12 +482,6 @@ func TestAnnotateObjectFromFile(t *testing.T) { ...@@ -486,12 +482,6 @@ func TestAnnotateObjectFromFile(t *testing.T) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/version":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil
default: default:
...@@ -513,7 +503,7 @@ func TestAnnotateObjectFromFile(t *testing.T) { ...@@ -513,7 +503,7 @@ func TestAnnotateObjectFromFile(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(f, buf) cmd := NewCmdAnnotate(f, buf)
...@@ -542,7 +532,7 @@ func TestAnnotateLocal(t *testing.T) { ...@@ -542,7 +532,7 @@ func TestAnnotateLocal(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(f, buf) cmd := NewCmdAnnotate(f, buf)
...@@ -572,12 +562,6 @@ func TestAnnotateMultipleObjects(t *testing.T) { ...@@ -572,12 +562,6 @@ func TestAnnotateMultipleObjects(t *testing.T) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/version":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil
default: default:
...@@ -601,7 +585,7 @@ func TestAnnotateMultipleObjects(t *testing.T) { ...@@ -601,7 +585,7 @@ func TestAnnotateMultipleObjects(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(f, buf) cmd := NewCmdAnnotate(f, buf)
......
...@@ -531,23 +531,13 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names ...@@ -531,23 +531,13 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names
} }
// Compute a three way strategic merge patch to send to server. // Compute a three way strategic merge patch to send to server.
patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, versionedObject, p.overwrite, strategicpatch.SMPatchVersion_1_5) patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, versionedObject, p.overwrite)
// If creating a patch fails, retrying with SMPatchVersion_1_0 is not helpful. So we return the error.
if err != nil { if err != nil {
format := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfor:" format := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfor:"
return nil, cmdutil.AddSourceToErr(fmt.Sprintf(format, original, modified, current), source, err) return nil, cmdutil.AddSourceToErr(fmt.Sprintf(format, original, modified, current), source, err)
} }
_, err = p.helper.Patch(namespace, name, api.StrategicMergePatchType, patch) _, err = p.helper.Patch(namespace, name, api.StrategicMergePatchType, patch)
if errors.IsInternalError(err) {
// Retry SMPatchVersion_1_0 when applying the SMPatchVersion_1_5 patch returns an Internal Error (500).
// Because the failure may be due to the server not supporting the SMPatchVersion_1_5 patch.
patch, err = strategicpatch.CreateThreeWayMergePatch(original, modified, current, versionedObject, p.overwrite, strategicpatch.SMPatchVersion_1_0)
if err != nil {
format := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfor:"
return nil, cmdutil.AddSourceToErr(fmt.Sprintf(format, original, modified, current), source, err)
}
_, err = p.helper.Patch(namespace, name, api.StrategicMergePatchType, patch)
}
return patch, err return patch, err
} }
......
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os" "os"
"strings"
"testing" "testing"
"github.com/spf13/cobra" "github.com/spf13/cobra"
...@@ -38,7 +37,6 @@ import ( ...@@ -38,7 +37,6 @@ import (
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/strategicpatch"
) )
func TestApplyExtraArgsFail(t *testing.T) { func TestApplyExtraArgsFail(t *testing.T) {
...@@ -144,58 +142,6 @@ func readAndAnnotateService(t *testing.T, filename string) (string, []byte) { ...@@ -144,58 +142,6 @@ func readAndAnnotateService(t *testing.T, filename string) (string, []byte) {
return annotateRuntimeObject(t, svc1, svc2, "Service") return annotateRuntimeObject(t, svc1, svc2, "Service")
} }
func setFinalizersRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object) (string, []byte) {
originalAccessor, err := meta.Accessor(originalObj)
if err != nil {
t.Fatal(err)
}
originalFinalizers := []string{"a/a"}
originalAccessor.SetFinalizers(originalFinalizers)
original, err := runtime.Encode(testapi.Default.Codec(), originalObj)
if err != nil {
t.Fatal(err)
}
currentAccessor, err := meta.Accessor(currentObj)
if err != nil {
t.Fatal(err)
}
currentFinalizers := []string{"b/b"}
currentAccessor.SetFinalizers(currentFinalizers)
currentAnnotations := currentAccessor.GetAnnotations()
if currentAnnotations == nil {
currentAnnotations = make(map[string]string)
}
currentAnnotations[annotations.LastAppliedConfigAnnotation] = string(original)
currentAccessor.SetAnnotations(currentAnnotations)
current, err := runtime.Encode(testapi.Default.Codec(), currentObj)
if err != nil {
t.Fatal(err)
}
return currentAccessor.GetName(), current
}
func readAndSetFinalizersReplicationController(t *testing.T, filename string) (string, []byte) {
rc1 := readReplicationControllerFromFile(t, filename)
rc2 := readReplicationControllerFromFile(t, filename)
name, rcBytes := setFinalizersRuntimeObject(t, rc1, rc2)
return name, rcBytes
}
func isSMPatchVersion_1_5(t *testing.T, req *http.Request) bool {
patch, err := ioutil.ReadAll(req.Body)
if err != nil {
t.Fatal(err)
}
// SMPatchVersion_1_5 patch should has string "mergeprimitiveslist"
return strings.Contains(string(patch), strategicpatch.MergePrimitivesListDirective)
}
func validatePatchApplication(t *testing.T, req *http.Request) { func validatePatchApplication(t *testing.T, req *http.Request) {
patch, err := ioutil.ReadAll(req.Body) patch, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
...@@ -242,12 +188,6 @@ func TestApplyObject(t *testing.T) { ...@@ -242,12 +188,6 @@ func TestApplyObject(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/version" && m == "GET":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil
...@@ -262,62 +202,6 @@ func TestApplyObject(t *testing.T) { ...@@ -262,62 +202,6 @@ func TestApplyObject(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdApply(f, buf)
cmd.Flags().Set("filename", filenameRC)
cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{})
// uses the name from the file, not the response
expectRC := "replicationcontroller/" + nameRC + "\n"
if buf.String() != expectRC {
t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expectRC)
}
}
func TestApplyRetryWithSMPatchVersion_1_5(t *testing.T) {
initTestErrorHandler(t)
nameRC, currentRC := readAndSetFinalizersReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
firstPatch := true
retry := false
f, tf, _, ns := cmdtesting.NewAPIFactory()
tf.Printer = &testPrinter{}
tf.Client = &fake.RESTClient{
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "PATCH":
if firstPatch {
if !isSMPatchVersion_1_5(t, req) {
t.Fatalf("apply didn't try to send SMPatchVersion_1_5 for the first time")
}
firstPatch = false
statusErr := kubeerr.NewInternalError(fmt.Errorf("Server encountered internal error."))
bodyBytes, _ := json.Marshal(statusErr)
bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes))
return &http.Response{StatusCode: http.StatusInternalServerError, Header: defaultHeader(), Body: bodyErr}, nil
}
retry = true
if isSMPatchVersion_1_5(t, req) {
t.Fatalf("apply didn't try to send SMPatchVersion_1_0 after SMPatchVersion_1_5 patch encounter an Internal Error (500)")
}
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdApply(f, buf) cmd := NewCmdApply(f, buf)
...@@ -325,10 +209,6 @@ func TestApplyRetryWithSMPatchVersion_1_5(t *testing.T) { ...@@ -325,10 +209,6 @@ func TestApplyRetryWithSMPatchVersion_1_5(t *testing.T) {
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
if !retry {
t.Fatalf("apply didn't retry when get Internal Error (500)")
}
// uses the name from the file, not the response // uses the name from the file, not the response
expectRC := "replicationcontroller/" + nameRC + "\n" expectRC := "replicationcontroller/" + nameRC + "\n"
if buf.String() != expectRC { if buf.String() != expectRC {
...@@ -350,12 +230,6 @@ func TestApplyRetry(t *testing.T) { ...@@ -350,12 +230,6 @@ func TestApplyRetry(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/version" && m == "GET":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
getCount++ getCount++
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
...@@ -379,7 +253,6 @@ func TestApplyRetry(t *testing.T) { ...@@ -379,7 +253,6 @@ func TestApplyRetry(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdApply(f, buf) cmd := NewCmdApply(f, buf)
...@@ -409,12 +282,6 @@ func TestApplyNonExistObject(t *testing.T) { ...@@ -409,12 +282,6 @@ func TestApplyNonExistObject(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/version" && m == "GET":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil
case p == pathNameRC && m == "GET": case p == pathNameRC && m == "GET":
...@@ -429,7 +296,6 @@ func TestApplyNonExistObject(t *testing.T) { ...@@ -429,7 +296,6 @@ func TestApplyNonExistObject(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdApply(f, buf) cmd := NewCmdApply(f, buf)
...@@ -465,12 +331,6 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { ...@@ -465,12 +331,6 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/version" && m == "GET":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil
...@@ -492,7 +352,6 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { ...@@ -492,7 +352,6 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdApply(f, buf) cmd := NewCmdApply(f, buf)
......
...@@ -39,13 +39,8 @@ import ( ...@@ -39,13 +39,8 @@ import (
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/version"
) )
var serverVersion_1_5_0 = version.Info{
GitVersion: "v1.5.0",
}
func initTestErrorHandler(t *testing.T) { func initTestErrorHandler(t *testing.T) {
cmdutil.BehaviorOnFatal(func(str string, code int) { cmdutil.BehaviorOnFatal(func(str string, code int) {
t.Errorf("Error running command (exit code %d): %s", code, str) t.Errorf("Error running command (exit code %d): %s", code, str)
......
...@@ -291,7 +291,7 @@ func runEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args ...@@ -291,7 +291,7 @@ func runEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args
switch editMode { switch editMode {
case NormalEditMode: case NormalEditMode:
err = visitToPatch(originalObj, updates, f, mapper, resourceMapper, encoder, out, errOut, defaultVersion, &results, file) err = visitToPatch(originalObj, updates, mapper, resourceMapper, encoder, out, errOut, defaultVersion, &results, file)
case EditBeforeCreateMode: case EditBeforeCreateMode:
err = visitToCreate(updates, mapper, resourceMapper, out, errOut, defaultVersion, &results, file) err = visitToCreate(updates, mapper, resourceMapper, out, errOut, defaultVersion, &results, file)
default: default:
...@@ -415,15 +415,7 @@ func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.File ...@@ -415,15 +415,7 @@ func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.File
return mapper, resourceMapper, r, cmdNamespace, err return mapper, resourceMapper, r, cmdNamespace, err
} }
func visitToPatch(originalObj runtime.Object, updates *resource.Info, func visitToPatch(originalObj runtime.Object, updates *resource.Info, mapper meta.RESTMapper, resourceMapper *resource.Mapper, encoder runtime.Encoder, out, errOut io.Writer, defaultVersion unversioned.GroupVersion, results *editResults, file string) error {
f cmdutil.Factory,
mapper meta.RESTMapper, resourceMapper *resource.Mapper,
encoder runtime.Encoder,
out, errOut io.Writer,
defaultVersion unversioned.GroupVersion,
results *editResults,
file string) error {
patchVisitor := resource.NewFlattenListVisitor(updates, resourceMapper) patchVisitor := resource.NewFlattenListVisitor(updates, resourceMapper)
err := patchVisitor.Visit(func(info *resource.Info, incomingErr error) error { err := patchVisitor.Visit(func(info *resource.Info, incomingErr error) error {
currOriginalObj := originalObj currOriginalObj := originalObj
...@@ -486,8 +478,7 @@ func visitToPatch(originalObj runtime.Object, updates *resource.Info, ...@@ -486,8 +478,7 @@ func visitToPatch(originalObj runtime.Object, updates *resource.Info,
preconditions := []strategicpatch.PreconditionFunc{strategicpatch.RequireKeyUnchanged("apiVersion"), preconditions := []strategicpatch.PreconditionFunc{strategicpatch.RequireKeyUnchanged("apiVersion"),
strategicpatch.RequireKeyUnchanged("kind"), strategicpatch.RequireMetadataKeyUnchanged("name")} strategicpatch.RequireKeyUnchanged("kind"), strategicpatch.RequireMetadataKeyUnchanged("name")}
patch, err := strategicpatch.CreateTwoWayMergePatch(originalJS, editedJS, currOriginalObj, strategicpatch.SMPatchVersion_1_5, preconditions...) patch, err := strategicpatch.CreateTwoWayMergePatch(originalJS, editedJS, currOriginalObj, preconditions...)
// If creating a patch fails, retrying with SMPatchVersion_1_0 is not helpful. So we return the error.
if err != nil { if err != nil {
glog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err) glog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
if strategicpatch.IsPreconditionFailed(err) { if strategicpatch.IsPreconditionFailed(err) {
...@@ -499,20 +490,8 @@ func visitToPatch(originalObj runtime.Object, updates *resource.Info, ...@@ -499,20 +490,8 @@ func visitToPatch(originalObj runtime.Object, updates *resource.Info,
results.version = defaultVersion results.version = defaultVersion
patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch)
if err != nil { if err != nil {
// Retry SMPatchVersion_1_0 when applying the SMPatchVersion_1_5 patch returns an Internal Error (500). fmt.Fprintln(out, results.addError(err, info))
// Because the failure may be due to the server not supporting the SMPatchVersion_1_5 patch. return nil
if errors.IsInternalError(err) {
patch, err = strategicpatch.CreateTwoWayMergePatch(originalJS, editedJS, currOriginalObj, strategicpatch.SMPatchVersion_1_0)
if err != nil {
glog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
return err
}
patched, err = resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch)
}
if err != nil {
fmt.Fprintln(out, results.addError(err, info))
return nil
}
} }
info.Refresh(patched, true) info.Refresh(patched, true)
cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, false, "edited") cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, false, "edited")
......
...@@ -246,8 +246,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { ...@@ -246,8 +246,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
if !reflect.DeepEqual(oldData, newData) { if !reflect.DeepEqual(oldData, newData) {
dataChangeMsg = "labeled" dataChangeMsg = "labeled"
} }
// Defaulting to SMPatchVersion_1_5 is safe, since we only update labels and change cause, and none of them has list of primitives patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj)
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj, strategicpatch.SMPatchVersion_1_5)
createdPatch := err == nil createdPatch := err == nil
if err != nil { if err != nil {
glog.V(2).Infof("couldn't compute patch: %v", err) glog.V(2).Infof("couldn't compute patch: %v", err)
......
...@@ -354,12 +354,6 @@ func TestLabelForResourceFromFile(t *testing.T) { ...@@ -354,12 +354,6 @@ func TestLabelForResourceFromFile(t *testing.T) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/version":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil
default: default:
...@@ -381,7 +375,7 @@ func TestLabelForResourceFromFile(t *testing.T) { ...@@ -381,7 +375,7 @@ func TestLabelForResourceFromFile(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdLabel(f, buf) cmd := NewCmdLabel(f, buf)
...@@ -443,12 +437,6 @@ func TestLabelMultipleObjects(t *testing.T) { ...@@ -443,12 +437,6 @@ func TestLabelMultipleObjects(t *testing.T) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/version":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil
default: default:
...@@ -472,7 +460,7 @@ func TestLabelMultipleObjects(t *testing.T) { ...@@ -472,7 +460,7 @@ func TestLabelMultipleObjects(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig() tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &registered.GroupOrDie(api.GroupName).GroupVersion}}
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdLabel(f, buf) cmd := NewCmdLabel(f, buf)
......
...@@ -34,12 +34,6 @@ func TestPatchObject(t *testing.T) { ...@@ -34,12 +34,6 @@ func TestPatchObject(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/version" && m == "GET":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil
default: default:
...@@ -49,7 +43,6 @@ func TestPatchObject(t *testing.T) { ...@@ -49,7 +43,6 @@ func TestPatchObject(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdPatch(f, buf) cmd := NewCmdPatch(f, buf)
...@@ -73,12 +66,6 @@ func TestPatchObjectFromFile(t *testing.T) { ...@@ -73,12 +66,6 @@ func TestPatchObjectFromFile(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/version" && m == "GET":
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil
default: default:
...@@ -88,7 +75,6 @@ func TestPatchObjectFromFile(t *testing.T) { ...@@ -88,7 +75,6 @@ func TestPatchObjectFromFile(t *testing.T) {
}), }),
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfig = defaultClientConfig()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdPatch(f, buf) cmd := NewCmdPatch(f, buf)
......
...@@ -32,7 +32,6 @@ go_library( ...@@ -32,7 +32,6 @@ go_library(
"//pkg/runtime:go_default_library", "//pkg/runtime:go_default_library",
"//pkg/util/errors:go_default_library", "//pkg/util/errors:go_default_library",
"//pkg/util/interrupt:go_default_library", "//pkg/util/interrupt:go_default_library",
"//pkg/util/strategicpatch:go_default_library",
"//pkg/watch:go_default_library", "//pkg/watch:go_default_library",
"//vendor:github.com/renstrom/dedent", "//vendor:github.com/renstrom/dedent",
"//vendor:github.com/spf13/cobra", "//vendor:github.com/spf13/cobra",
......
...@@ -31,7 +31,6 @@ import ( ...@@ -31,7 +31,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/strategicpatch"
) )
// PauseConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of // PauseConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of
...@@ -39,7 +38,6 @@ import ( ...@@ -39,7 +38,6 @@ import (
type PauseConfig struct { type PauseConfig struct {
resource.FilenameOptions resource.FilenameOptions
f cmdutil.Factory
Pauser func(info *resource.Info) (bool, error) Pauser func(info *resource.Info) (bool, error)
Mapper meta.RESTMapper Mapper meta.RESTMapper
Typer runtime.ObjectTyper Typer runtime.ObjectTyper
...@@ -101,7 +99,6 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i ...@@ -101,7 +99,6 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i
return cmdutil.UsageError(cmd, cmd.Use) return cmdutil.UsageError(cmd, cmd.Use)
} }
o.f = f
o.Mapper, o.Typer = f.Object() o.Mapper, o.Typer = f.Object()
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
...@@ -135,8 +132,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i ...@@ -135,8 +132,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i
func (o PauseConfig) RunPause() error { func (o PauseConfig) RunPause() error {
allErrs := []error{} allErrs := []error{}
// Defaulting to SMPatchVersion_1_5 is safe, since Pauser only update a boolean variable for _, patch := range set.CalculatePatches(o.Infos, o.Encoder, o.Pauser) {
for _, patch := range set.CalculatePatches(o.f, o.Infos, o.Encoder, strategicpatch.SMPatchVersion_1_5, o.Pauser) {
info := patch.Info info := patch.Info
if patch.Err != nil { if patch.Err != nil {
allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", info.Mapping.Resource, info.Name, patch.Err)) allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", info.Mapping.Resource, info.Name, patch.Err))
......
...@@ -31,7 +31,6 @@ import ( ...@@ -31,7 +31,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/strategicpatch"
) )
// ResumeConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of // ResumeConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of
...@@ -39,7 +38,6 @@ import ( ...@@ -39,7 +38,6 @@ import (
type ResumeConfig struct { type ResumeConfig struct {
resource.FilenameOptions resource.FilenameOptions
f cmdutil.Factory
Resumer func(object *resource.Info) (bool, error) Resumer func(object *resource.Info) (bool, error)
Mapper meta.RESTMapper Mapper meta.RESTMapper
Typer runtime.ObjectTyper Typer runtime.ObjectTyper
...@@ -99,7 +97,6 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out ...@@ -99,7 +97,6 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out
return cmdutil.UsageError(cmd, cmd.Use) return cmdutil.UsageError(cmd, cmd.Use)
} }
o.f = f
o.Mapper, o.Typer = f.Object() o.Mapper, o.Typer = f.Object()
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
...@@ -139,8 +136,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out ...@@ -139,8 +136,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out
func (o ResumeConfig) RunResume() error { func (o ResumeConfig) RunResume() error {
allErrs := []error{} allErrs := []error{}
// Defaulting to SMPatchVersion_1_5 is safe, since Resumer only update a boolean variable for _, patch := range set.CalculatePatches(o.Infos, o.Encoder, o.Resumer) {
for _, patch := range set.CalculatePatches(o.f, o.Infos, o.Encoder, strategicpatch.SMPatchVersion_1_5, o.Resumer) {
info := patch.Info info := patch.Info
if patch.Err != nil { if patch.Err != nil {
......
...@@ -23,7 +23,7 @@ import ( ...@@ -23,7 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/strategicpatch" "k8s.io/kubernetes/pkg/util/strategicpatch"
...@@ -61,7 +61,7 @@ func handlePodUpdateError(out io.Writer, err error, resource string) { ...@@ -61,7 +61,7 @@ func handlePodUpdateError(out io.Writer, err error, resource string) {
return return
} }
} else { } else {
if ok := cmdutil.PrintErrorWithCauses(err, out); ok { if ok := kcmdutil.PrintErrorWithCauses(err, out); ok {
return return
} }
} }
...@@ -120,10 +120,7 @@ type Patch struct { ...@@ -120,10 +120,7 @@ type Patch struct {
// CalculatePatches calls the mutation function on each provided info object, and generates a strategic merge patch for // CalculatePatches calls the mutation function on each provided info object, and generates a strategic merge patch for
// the changes in the object. Encoder must be able to encode the info into the appropriate destination type. If mutateFn // the changes in the object. Encoder must be able to encode the info into the appropriate destination type. If mutateFn
// returns false, the object is not included in the final list of patches. // returns false, the object is not included in the final list of patches.
// If local is true, it will be default to use SMPatchVersionLatest to calculate a patch without contacting the server to func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn func(*resource.Info) (bool, error)) []*Patch {
// get the server supported SMPatchVersion. If you are using a patch's Patch field generated in local mode, be careful.
// If local is false, it will talk to the server to check which StategicMergePatchVersion to use.
func CalculatePatches(f cmdutil.Factory, infos []*resource.Info, encoder runtime.Encoder, smPatchVersion strategicpatch.StrategicMergePatchVersion, mutateFn func(*resource.Info) (bool, error)) []*Patch {
var patches []*Patch var patches []*Patch
for _, info := range infos { for _, info := range infos {
patch := &Patch{Info: info} patch := &Patch{Info: info}
...@@ -159,7 +156,7 @@ func CalculatePatches(f cmdutil.Factory, infos []*resource.Info, encoder runtime ...@@ -159,7 +156,7 @@ func CalculatePatches(f cmdutil.Factory, infos []*resource.Info, encoder runtime
continue continue
} }
patch.Patch, patch.Err = strategicpatch.CreateTwoWayMergePatch(patch.Before, patch.After, versioned, smPatchVersion) patch.Patch, patch.Err = strategicpatch.CreateTwoWayMergePatch(patch.Before, patch.After, versioned)
} }
return patches return patches
} }
...@@ -28,7 +28,6 @@ import ( ...@@ -28,7 +28,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/strategicpatch"
) )
// ImageOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // ImageOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
...@@ -36,7 +35,6 @@ import ( ...@@ -36,7 +35,6 @@ import (
type ImageOptions struct { type ImageOptions struct {
resource.FilenameOptions resource.FilenameOptions
f cmdutil.Factory
Mapper meta.RESTMapper Mapper meta.RESTMapper
Typer runtime.ObjectTyper Typer runtime.ObjectTyper
Infos []*resource.Info Infos []*resource.Info
...@@ -110,7 +108,6 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { ...@@ -110,7 +108,6 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
} }
func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.f = f
o.Mapper, o.Typer = f.Object() o.Mapper, o.Typer = f.Object()
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
...@@ -164,8 +161,8 @@ func (o *ImageOptions) Validate() error { ...@@ -164,8 +161,8 @@ func (o *ImageOptions) Validate() error {
func (o *ImageOptions) Run() error { func (o *ImageOptions) Run() error {
allErrs := []error{} allErrs := []error{}
// Defauting to SMPatchVersion_1_5, since the func passed in doesn't update any lists of primitive
patches := CalculatePatches(o.f, o.Infos, o.Encoder, strategicpatch.SMPatchVersion_1_5, func(info *resource.Info) (bool, error) { patches := CalculatePatches(o.Infos, o.Encoder, func(info *resource.Info) (bool, error) {
transformed := false transformed := false
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error { _, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error {
for name, image := range o.ContainerImages { for name, image := range o.ContainerImages {
......
...@@ -31,7 +31,6 @@ import ( ...@@ -31,7 +31,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/strategicpatch"
) )
var ( var (
...@@ -61,7 +60,6 @@ var ( ...@@ -61,7 +60,6 @@ var (
type ResourcesOptions struct { type ResourcesOptions struct {
resource.FilenameOptions resource.FilenameOptions
f cmdutil.Factory
Mapper meta.RESTMapper Mapper meta.RESTMapper
Typer runtime.ObjectTyper Typer runtime.ObjectTyper
Infos []*resource.Info Infos []*resource.Info
...@@ -126,7 +124,6 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra. ...@@ -126,7 +124,6 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.
} }
func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.f = f
o.Mapper, o.Typer = f.Object() o.Mapper, o.Typer = f.Object()
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
...@@ -177,8 +174,7 @@ func (o *ResourcesOptions) Validate() error { ...@@ -177,8 +174,7 @@ func (o *ResourcesOptions) Validate() error {
func (o *ResourcesOptions) Run() error { func (o *ResourcesOptions) Run() error {
allErrs := []error{} allErrs := []error{}
// Defauting to SMPatchVersion_1_5, since the func passed in doesn't update any lists of primitive patches := CalculatePatches(o.Infos, o.Encoder, func(info *resource.Info) (bool, error) {
patches := CalculatePatches(o.f, o.Infos, o.Encoder, strategicpatch.SMPatchVersion_1_5, func(info *resource.Info) (bool, error) {
transformed := false transformed := false
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error { _, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error {
containers, _ := selectContainers(spec.Containers, o.ContainerSelector) containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
......
...@@ -343,8 +343,7 @@ func (o TaintOptions) RunTaint() error { ...@@ -343,8 +343,7 @@ func (o TaintOptions) RunTaint() error {
if err != nil { if err != nil {
return err return err
} }
// Defaulting to SMPatchVersion_1_5 is safe, since we don't update list of primitives. patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj)
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj, strategicpatch.SMPatchVersion_1_5)
createdPatch := err == nil createdPatch := err == nil
if err != nil { if err != nil {
glog.V(2).Infof("couldn't compute patch: %v", err) glog.V(2).Infof("couldn't compute patch: %v", err)
......
...@@ -252,6 +252,7 @@ func TestTaint(t *testing.T) { ...@@ -252,6 +252,7 @@ func TestTaint(t *testing.T) {
for _, test := range tests { for _, test := range tests {
oldNode, expectNewNode := generateNodeAndTaintedNode(test.oldTaints, test.newTaints) oldNode, expectNewNode := generateNodeAndTaintedNode(test.oldTaints, test.newTaints)
new_node := &api.Node{} new_node := &api.Node{}
tainted := false tainted := false
f, tf, codec, ns := cmdtesting.NewAPIFactory() f, tf, codec, ns := cmdtesting.NewAPIFactory()
...@@ -261,12 +262,6 @@ func TestTaint(t *testing.T) { ...@@ -261,12 +262,6 @@ func TestTaint(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
m := &MyReq{req} m := &MyReq{req}
switch { switch {
case m.isFor("GET", "/version"):
resp, err := genResponseWithJsonEncodedBody(serverVersion_1_5_0)
if err != nil {
t.Fatalf("error: failed to generate server version response: %#v\n", serverVersion_1_5_0)
}
return resp, nil
case m.isFor("GET", "/nodes/node-name"): case m.isFor("GET", "/nodes/node-name"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil
case m.isFor("PATCH", "/nodes/node-name"), m.isFor("PUT", "/nodes/node-name"): case m.isFor("PATCH", "/nodes/node-name"), m.isFor("PUT", "/nodes/node-name"):
......
...@@ -427,12 +427,8 @@ func (f *fakeAPIFactory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectTy ...@@ -427,12 +427,8 @@ func (f *fakeAPIFactory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectTy
return cmdutil.NewShortcutExpander(mapper, nil), typer, nil return cmdutil.NewShortcutExpander(mapper, nil), typer, nil
} }
func (f *fakeAPIFactory) Decoder(toInternal bool) runtime.Decoder { func (f *fakeAPIFactory) Decoder(bool) runtime.Decoder {
if toInternal { return testapi.Default.Codec()
return api.Codecs.UniversalDecoder()
} else {
return api.Codecs.UniversalDeserializer()
}
} }
func (f *fakeAPIFactory) JSONEncoder() runtime.Encoder { func (f *fakeAPIFactory) JSONEncoder() runtime.Encoder {
......
...@@ -533,8 +533,7 @@ func ChangeResourcePatch(info *resource.Info, changeCause string) ([]byte, error ...@@ -533,8 +533,7 @@ func ChangeResourcePatch(info *resource.Info, changeCause string) ([]byte, error
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Using SMPatchVersion_1_5, since RecordChangeCause() just update the annotation which is a map[string]string return strategicpatch.CreateTwoWayMergePatch(oldData, newData, info.Object)
return strategicpatch.CreateTwoWayMergePatch(oldData, newData, info.Object, strategicpatch.SMPatchVersion_1_5)
} }
// containsChangeCause checks if input resource info contains change-cause annotation. // containsChangeCause checks if input resource info contains change-cause annotation.
......
apiVersion: v1 apiVersion: v1
kind: ReplicationController kind: ReplicationController
metadata: metadata:
finalizers:
- b/b
name: test-rc name: test-rc
labels: labels:
name: test-rc name: test-rc
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment