mirror of https://github.com/k3s-io/k3s
Merge pull request #22634 from kargakis/kubectl-edit-error-log-fix
Auto commit by PR queue botpull/6/head
commit
9dfbcae449
|
@ -164,7 +164,7 @@ Find more information at https://github.com/kubernetes/kubernetes.`,
|
||||||
cmds.AddCommand(NewCmdReplace(f, out))
|
cmds.AddCommand(NewCmdReplace(f, out))
|
||||||
cmds.AddCommand(NewCmdPatch(f, out))
|
cmds.AddCommand(NewCmdPatch(f, out))
|
||||||
cmds.AddCommand(NewCmdDelete(f, out))
|
cmds.AddCommand(NewCmdDelete(f, out))
|
||||||
cmds.AddCommand(NewCmdEdit(f, out))
|
cmds.AddCommand(NewCmdEdit(f, out, err))
|
||||||
cmds.AddCommand(NewCmdApply(f, out))
|
cmds.AddCommand(NewCmdApply(f, out))
|
||||||
|
|
||||||
cmds.AddCommand(NewCmdNamespace(out))
|
cmds.AddCommand(NewCmdNamespace(out))
|
||||||
|
|
|
@ -76,7 +76,7 @@ saved copy to include the latest resource version.`
|
||||||
|
|
||||||
var errExit = fmt.Errorf("exit directly")
|
var errExit = fmt.Errorf("exit directly")
|
||||||
|
|
||||||
func NewCmdEdit(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||||
filenames := []string{}
|
filenames := []string{}
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "edit (RESOURCE/NAME | -f FILENAME)",
|
Use: "edit (RESOURCE/NAME | -f FILENAME)",
|
||||||
|
@ -84,7 +84,7 @@ func NewCmdEdit(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
Long: editLong,
|
Long: editLong,
|
||||||
Example: fmt.Sprintf(editExample),
|
Example: fmt.Sprintf(editExample),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunEdit(f, out, cmd, args, filenames)
|
err := RunEdit(f, out, errOut, cmd, args, filenames)
|
||||||
if err == errExit {
|
if err == errExit {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ func NewCmdEdit(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunEdit(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames []string) error {
|
func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, filenames []string) error {
|
||||||
var printer kubectl.ResourcePrinter
|
var printer kubectl.ResourcePrinter
|
||||||
var ext string
|
var ext string
|
||||||
switch format := cmdutil.GetFlagString(cmd, "output"); format {
|
switch format := cmdutil.GetFlagString(cmd, "output"); format {
|
||||||
|
@ -184,11 +184,11 @@ outter:
|
||||||
w = crlf.NewCRLFWriter(w)
|
w = crlf.NewCRLFWriter(w)
|
||||||
}
|
}
|
||||||
if err := results.header.writeTo(w); err != nil {
|
if err := results.header.writeTo(w); err != nil {
|
||||||
return preservedFile(err, results.file, out)
|
return preservedFile(err, results.file, errOut)
|
||||||
}
|
}
|
||||||
if !containsError {
|
if !containsError {
|
||||||
if err := printer.PrintObj(obj, w); err != nil {
|
if err := printer.PrintObj(obj, w); err != nil {
|
||||||
return preservedFile(err, results.file, out)
|
return preservedFile(err, results.file, errOut)
|
||||||
}
|
}
|
||||||
original = buf.Bytes()
|
original = buf.Bytes()
|
||||||
} else {
|
} else {
|
||||||
|
@ -202,7 +202,7 @@ outter:
|
||||||
editedDiff := edited
|
editedDiff := edited
|
||||||
edited, file, err = edit.LaunchTempFile(fmt.Sprintf("%s-edit-", path.Base(os.Args[0])), ext, buf)
|
edited, file, err = edit.LaunchTempFile(fmt.Sprintf("%s-edit-", path.Base(os.Args[0])), ext, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return preservedFile(err, results.file, out)
|
return preservedFile(err, results.file, errOut)
|
||||||
}
|
}
|
||||||
if bytes.Equal(stripComments(editedDiff), stripComments(edited)) {
|
if bytes.Equal(stripComments(editedDiff), stripComments(edited)) {
|
||||||
// Ugly hack right here. We will hit this either (1) when we try to
|
// Ugly hack right here. We will hit this either (1) when we try to
|
||||||
|
@ -210,7 +210,7 @@ outter:
|
||||||
// which means our changes are invalid or (2) when we exit the second
|
// which means our changes are invalid or (2) when we exit the second
|
||||||
// time. The second case is more usual so we can probably live with it.
|
// time. The second case is more usual so we can probably live with it.
|
||||||
// TODO: A less hacky fix would be welcome :)
|
// TODO: A less hacky fix would be welcome :)
|
||||||
fmt.Fprintln(out, "Edit cancelled, no valid changes were saved.")
|
fmt.Fprintln(errOut, "Edit cancelled, no valid changes were saved.")
|
||||||
continue outter
|
continue outter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,16 +223,16 @@ outter:
|
||||||
// Compare content without comments
|
// Compare content without comments
|
||||||
if bytes.Equal(stripComments(original), stripComments(edited)) {
|
if bytes.Equal(stripComments(original), stripComments(edited)) {
|
||||||
os.Remove(file)
|
os.Remove(file)
|
||||||
fmt.Fprintln(out, "Edit cancelled, no changes made.")
|
fmt.Fprintln(errOut, "Edit cancelled, no changes made.")
|
||||||
continue outter
|
continue outter
|
||||||
}
|
}
|
||||||
lines, err := hasLines(bytes.NewBuffer(edited))
|
lines, err := hasLines(bytes.NewBuffer(edited))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
}
|
}
|
||||||
if !lines {
|
if !lines {
|
||||||
os.Remove(file)
|
os.Remove(file)
|
||||||
fmt.Fprintln(out, "Edit cancelled, saved file was empty.")
|
fmt.Fprintln(errOut, "Edit cancelled, saved file was empty.")
|
||||||
continue outter
|
continue outter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ outter:
|
||||||
|
|
||||||
// put configuration annotation in "updates"
|
// put configuration annotation in "updates"
|
||||||
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), updates, encoder); err != nil {
|
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), updates, encoder); err != nil {
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
}
|
}
|
||||||
if cmdutil.ShouldRecord(cmd, updates) {
|
if cmdutil.ShouldRecord(cmd, updates) {
|
||||||
err = cmdutil.RecordChangeCause(updates.Object, f.Command())
|
err = cmdutil.RecordChangeCause(updates.Object, f.Command())
|
||||||
|
@ -263,24 +263,24 @@ outter:
|
||||||
}
|
}
|
||||||
editedCopy := edited
|
editedCopy := edited
|
||||||
if editedCopy, err = runtime.Encode(encoder, updates.Object); err != nil {
|
if editedCopy, err = runtime.Encode(encoder, updates.Object); err != nil {
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor := resource.NewFlattenListVisitor(updates, resourceMapper)
|
visitor := resource.NewFlattenListVisitor(updates, resourceMapper)
|
||||||
|
|
||||||
// need to make sure the original namespace wasn't changed while editing
|
// need to make sure the original namespace wasn't changed while editing
|
||||||
if err = visitor.Visit(resource.RequireNamespace(cmdNamespace)); err != nil {
|
if err = visitor.Visit(resource.RequireNamespace(cmdNamespace)); err != nil {
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
// use strategic merge to create a patch
|
// use strategic merge to create a patch
|
||||||
originalJS, err := yaml.ToJSON(original)
|
originalJS, err := yaml.ToJSON(original)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
}
|
}
|
||||||
editedJS, err := yaml.ToJSON(editedCopy)
|
editedJS, err := yaml.ToJSON(editedCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
}
|
}
|
||||||
patch, err := strategicpatch.CreateStrategicMergePatch(originalJS, editedJS, obj)
|
patch, err := strategicpatch.CreateStrategicMergePatch(originalJS, editedJS, obj)
|
||||||
// TODO: change all jsonmerge to strategicpatch
|
// TODO: change all jsonmerge to strategicpatch
|
||||||
|
@ -288,7 +288,7 @@ outter:
|
||||||
preconditions := []jsonmerge.PreconditionFunc{}
|
preconditions := []jsonmerge.PreconditionFunc{}
|
||||||
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)
|
||||||
return preservedFile(err, file, out)
|
return preservedFile(err, file, errOut)
|
||||||
} else {
|
} else {
|
||||||
preconditions = append(preconditions, jsonmerge.RequireKeyUnchanged("apiVersion"))
|
preconditions = append(preconditions, jsonmerge.RequireKeyUnchanged("apiVersion"))
|
||||||
preconditions = append(preconditions, jsonmerge.RequireKeyUnchanged("kind"))
|
preconditions = append(preconditions, jsonmerge.RequireKeyUnchanged("kind"))
|
||||||
|
@ -297,14 +297,15 @@ outter:
|
||||||
}
|
}
|
||||||
|
|
||||||
if hold, msg := jsonmerge.TestPreconditionsHold(patch, preconditions); !hold {
|
if hold, msg := jsonmerge.TestPreconditionsHold(patch, preconditions); !hold {
|
||||||
fmt.Fprintf(out, "error: %s", msg)
|
fmt.Fprintf(errOut, "error: %s\n", msg)
|
||||||
return preservedFile(nil, file, out)
|
return preservedFile(nil, file, errOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorMsg := ""
|
||||||
err = visitor.Visit(func(info *resource.Info, err error) error {
|
err = visitor.Visit(func(info *resource.Info, err error) error {
|
||||||
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 {
|
||||||
glog.V(4).Infof(results.addError(err, info))
|
errorMsg = results.addError(err, info)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
info.Refresh(patched, true)
|
info.Refresh(patched, true)
|
||||||
|
@ -321,11 +322,13 @@ outter:
|
||||||
// 2. notfound: indicate the location of the saved configuration of the deleted resource
|
// 2. notfound: indicate the location of the saved configuration of the deleted resource
|
||||||
// 3. invalid: retry those on the spot by looping ie. reloading the editor
|
// 3. invalid: retry those on the spot by looping ie. reloading the editor
|
||||||
if results.retryable > 0 {
|
if results.retryable > 0 {
|
||||||
fmt.Fprintf(out, "You can run `%s replace -f %s` to try this update again.\n", os.Args[0], file)
|
fmt.Fprintln(errOut, errorMsg)
|
||||||
|
fmt.Fprintf(errOut, "You can run `%s replace -f %s` to try this update again.\n", path.Base(os.Args[0]), file)
|
||||||
continue outter
|
continue outter
|
||||||
}
|
}
|
||||||
if results.notfound > 0 {
|
if results.notfound > 0 {
|
||||||
fmt.Fprintf(out, "The edits you made on deleted resources have been saved to %q\n", file)
|
fmt.Fprintln(errOut, errorMsg)
|
||||||
|
fmt.Fprintf(errOut, "The edits you made on deleted resources have been saved to %q\n", file)
|
||||||
continue outter
|
continue outter
|
||||||
}
|
}
|
||||||
// validation error
|
// validation error
|
||||||
|
@ -397,13 +400,13 @@ func (r *editResults) addError(err error, info *resource.Info) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.header.reasons = append(r.header.reasons, reason)
|
r.header.reasons = append(r.header.reasons, reason)
|
||||||
return fmt.Sprintf("Error: %s %q is invalid", info.Mapping.Resource, info.Name)
|
return fmt.Sprintf("error: %s %q is invalid", info.Mapping.Resource, info.Name)
|
||||||
case errors.IsNotFound(err):
|
case errors.IsNotFound(err):
|
||||||
r.notfound++
|
r.notfound++
|
||||||
return fmt.Sprintf("Error: %s %q could not be found on the server", info.Mapping.Resource, info.Name)
|
return fmt.Sprintf("error: %s %q could not be found on the server", info.Mapping.Resource, info.Name)
|
||||||
default:
|
default:
|
||||||
r.retryable++
|
r.retryable++
|
||||||
return fmt.Sprintf("Error: %s %q could not be patched: %v", info.Mapping.Resource, info.Name, err)
|
return fmt.Sprintf("error: %s %q could not be patched: %v", info.Mapping.Resource, info.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue