easegress icon indicating copy to clipboard operation
easegress copied to clipboard

Easegress egctl cmd enhancement

Open jthann opened this issue 2 years ago • 5 comments

Is egctl has any way to delete all objects using just one command, right now I can put all Easegress objects(including HTTPServer、GlobalFilter、NacosServiceRegistry、HTTPPipeline etc) in a file and use just one command egctl object create -f file to create. But for any reason if I change one of these objects especially for local debug,it is very hard for me to apply these new changes(I need to delete local etcd data dir and restart), I think egctl should like k8s kubectl to support egctl object apply -f file in a declarative way.

jthann avatar Jan 28 '22 08:01 jthann

Sounds like a nice improvement! I also often struggle with delete/create. apply command that updates only changed resources is much better UX

samutamm avatar Jan 28 '22 08:01 samutamm

I'v just found egctl object update -f file.yaml can solve the problem to some extent,so I close this issue. Anyway for better UX, we need some way like kubectl apply and namespace isolation to support multi env(another issue)

jthann avatar Jan 28 '22 08:01 jthann

First we should add egctl object delete -f <yaml file_name> operation,right now it only has egctl object delete <object_name>

jthann avatar Jan 28 '22 08:01 jthann

I just do a simple origin egctl cmd wrapper and compiled binary named as egctl+ for delete all and apply subcommand, add egctl+ and egctl path to executable path, just for local debug anyway.

package main

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"log"
	"os"
	"os/exec"
)

type ObjectSpec struct {
	Kind string `yaml:"kind"`
	Name string `yaml:"name"`
}

func main() {
	if isDelAllCmd() {
		execDelAllCmd()
	} else if isApplyCmd() {
		execDelAllCmd()
		execOriginCmd([]string{"object", "create", "-f", os.Args[len(os.Args)-1]})
	} else {
		execOriginCmd(os.Args[1:])
	}
}

func isApplyCmd() bool {
	//egctl+ object apply -f file
	return len(os.Args) == 5 && os.Args[1] == "object" && os.Args[2] == "apply" && os.Args[3] == "-f" && os.Args[4] != ""
}

func isDelAllCmd() bool {
	//egctl+ object delete --all
	return len(os.Args) == 4 && os.Args[1] == "object" && os.Args[2] == "delete" && os.Args[3] == "--all"
}

func execOriginCmd(args []string) {
	cmd := exec.Command("egctl", args...)
	output, err := cmd.Output()
	if err != nil {
		log.Fatalf("execute cmd %s %s err %s", cmd.Path, cmd.Args, err)
	}
	fmt.Print(string(output))
}

func execDelAllCmd() {
	cmd := exec.Command("egctl", "object", "list")
	output, err := cmd.Output()
	if err != nil {
		log.Fatalf("execute cmd output: %s", err)
	}
	var objSpecs []*ObjectSpec
	err = yaml.Unmarshal(output, &objSpecs)
	if err != nil {
		log.Fatalf("unmarshal object specs failure: %s", err)
	}
	var cmds []*exec.Cmd
	for _, spec := range objSpecs {
		cmds = append(cmds, exec.Command("egctl", "object", "delete", spec.Name))
	}
	for _, cmd := range cmds {
		_, err := cmd.Output()
		if err != nil {
			log.Fatalf("execute cmd %s %s err %s", cmd.Path, cmd.Args, err)
		}
	}
}

jthann avatar Jan 29 '22 08:01 jthann

Very clever and simple way to add delete --all and apply 💯 @jthann

I think that it would be nice to implement it in egctl tool too. However I would prefer if the apply would not delete anything, just like in Kubernetes kubectl tool. kubectl apply documentation does

a three-way diff between the previous configuration, the provided input and the current configuration of the resource, in order to determine how to modify the resource

What about others, do you think we should have apply in egctl? Should it be similar to k8s version, with three-way diff? @suchen-sci @xxx7xxxx @localvar

samutamm avatar Jan 29 '22 10:01 samutamm

egctl is enhanced now. Please check.

suchen-sci avatar Aug 16 '23 10:08 suchen-sci