mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 07:27:21 +00:00
support editing before creating resource
This commit is contained in:
@@ -118,12 +118,16 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
}
|
||||
|
||||
func RunEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error {
|
||||
return runEdit(f, out, errOut, cmd, args, options, NormalEditMode)
|
||||
}
|
||||
|
||||
func runEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions, editMode EditMode) error {
|
||||
o, err := getPrinter(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mapper, resourceMapper, r, cmdNamespace, err := getMapperAndResult(f, args, options)
|
||||
mapper, resourceMapper, r, cmdNamespace, err := getMapperAndResult(f, args, options, editMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -192,14 +196,15 @@ func RunEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args
|
||||
if err != nil {
|
||||
return preservedFile(err, results.file, errOut)
|
||||
}
|
||||
if bytes.Equal(stripComments(editedDiff), stripComments(edited)) {
|
||||
// Ugly hack right here. We will hit this either (1) when we try to
|
||||
// save the same changes we tried to save in the previous iteration
|
||||
// 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.
|
||||
// TODO: A less hacky fix would be welcome :)
|
||||
fmt.Fprintln(errOut, "Edit cancelled, no valid changes were saved.")
|
||||
return nil
|
||||
if editMode == NormalEditMode || containsError {
|
||||
if bytes.Equal(stripComments(editedDiff), stripComments(edited)) {
|
||||
// Ugly hack right here. We will hit this either (1) when we try to
|
||||
// save the same changes we tried to save in the previous iteration
|
||||
// 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.
|
||||
// TODO: A less hacky fix would be welcome :)
|
||||
return preservedFile(fmt.Errorf("%s", "Edit cancelled, no valid changes were saved."), file, errOut)
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup any file from the previous pass
|
||||
@@ -229,6 +234,7 @@ func RunEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args
|
||||
fmt.Fprintln(errOut, "Edit cancelled, no changes made.")
|
||||
return nil
|
||||
}
|
||||
|
||||
lines, err := hasLines(bytes.NewBuffer(edited))
|
||||
if err != nil {
|
||||
return preservedFile(err, file, errOut)
|
||||
@@ -271,7 +277,14 @@ func RunEdit(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args
|
||||
meta.SetList(updates.Object, mutatedObjects)
|
||||
}
|
||||
|
||||
err = visitToPatch(originalObj, updates, mapper, resourceMapper, encoder, out, errOut, defaultVersion, &results, file)
|
||||
switch editMode {
|
||||
case NormalEditMode:
|
||||
err = visitToPatch(originalObj, updates, mapper, resourceMapper, encoder, out, errOut, defaultVersion, &results, file)
|
||||
case EditBeforeCreateMode:
|
||||
err = visitToCreate(updates, mapper, resourceMapper, out, errOut, defaultVersion, &results, file)
|
||||
default:
|
||||
err = fmt.Errorf("Not supported edit mode %q", editMode)
|
||||
}
|
||||
if err != nil {
|
||||
return preservedFile(err, results.file, errOut)
|
||||
}
|
||||
@@ -315,7 +328,8 @@ func getPrinter(cmd *cobra.Command) (*editPrinterOptions, error) {
|
||||
ext: ".json",
|
||||
addHeader: false,
|
||||
}, nil
|
||||
case "yaml":
|
||||
// If flag -o is not specified, use yaml as default
|
||||
case "yaml", "":
|
||||
return &editPrinterOptions{
|
||||
printer: &kubectl.YAMLPrinter{},
|
||||
ext: ".yaml",
|
||||
@@ -326,13 +340,24 @@ func getPrinter(cmd *cobra.Command) (*editPrinterOptions, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.FilenameOptions) (meta.RESTMapper, *resource.Mapper, *resource.Result, string, error) {
|
||||
func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.FilenameOptions, editMode EditMode) (meta.RESTMapper, *resource.Mapper, *resource.Result, string, error) {
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return nil, nil, nil, "", err
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
var mapper meta.RESTMapper
|
||||
var typer runtime.ObjectTyper
|
||||
switch editMode {
|
||||
case NormalEditMode:
|
||||
mapper, typer = f.Object()
|
||||
case EditBeforeCreateMode:
|
||||
mapper, typer, err = f.UnstructuredObject()
|
||||
default:
|
||||
return nil, nil, nil, "", fmt.Errorf("Not supported edit mode %q", editMode)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, nil, "", err
|
||||
}
|
||||
resourceMapper := &resource.Mapper{
|
||||
ObjectTyper: typer,
|
||||
RESTMapper: mapper,
|
||||
@@ -345,14 +370,21 @@ func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.File
|
||||
// compare two different GroupVersions).
|
||||
Decoder: f.Decoder(false),
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
var b *resource.Builder
|
||||
switch editMode {
|
||||
case NormalEditMode:
|
||||
b = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
Latest()
|
||||
case EditBeforeCreateMode:
|
||||
b = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme)
|
||||
default:
|
||||
return nil, nil, nil, "", fmt.Errorf("Not supported edit mode %q", editMode)
|
||||
}
|
||||
r := b.NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
ContinueOnError().
|
||||
Flatten().
|
||||
Latest().
|
||||
Do()
|
||||
err = r.Err()
|
||||
if err != nil {
|
||||
@@ -428,7 +460,7 @@ func visitToPatch(originalObj runtime.Object, updates *resource.Info, mapper met
|
||||
if err != nil {
|
||||
glog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err)
|
||||
if strategicpatch.IsPreconditionFailed(err) {
|
||||
return preservedFile(nil, file, errOut)
|
||||
return fmt.Errorf("%s", "At least one of apiVersion, kind and name was changed")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -446,6 +478,19 @@ func visitToPatch(originalObj runtime.Object, updates *resource.Info, mapper met
|
||||
return err
|
||||
}
|
||||
|
||||
func visitToCreate(updates *resource.Info, mapper meta.RESTMapper, resourceMapper *resource.Mapper, out, errOut io.Writer, defaultVersion unversioned.GroupVersion, results *editResults, file string) error {
|
||||
createVisitor := resource.NewFlattenListVisitor(updates, resourceMapper)
|
||||
err := createVisitor.Visit(func(info *resource.Info, incomingErr error) error {
|
||||
results.version = defaultVersion
|
||||
if err := createAndRefresh(info); err != nil {
|
||||
return err
|
||||
}
|
||||
cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, false, "created")
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func visitAnnotation(cmd *cobra.Command, f cmdutil.Factory, updates *resource.Info, resourceMapper *resource.Mapper, encoder runtime.Encoder) ([]runtime.Object, error) {
|
||||
mutatedObjects := []runtime.Object{}
|
||||
annotationVisitor := resource.NewFlattenListVisitor(updates, resourceMapper)
|
||||
@@ -468,6 +513,13 @@ func visitAnnotation(cmd *cobra.Command, f cmdutil.Factory, updates *resource.In
|
||||
return mutatedObjects, err
|
||||
}
|
||||
|
||||
type EditMode string
|
||||
|
||||
const (
|
||||
NormalEditMode EditMode = "normal_mode"
|
||||
EditBeforeCreateMode EditMode = "edit_before_create_mode"
|
||||
)
|
||||
|
||||
// editReason preserves a message about the reason this file must be edited again
|
||||
type editReason struct {
|
||||
head string
|
||||
|
||||
Reference in New Issue
Block a user