From 4577a12a612a8129597a7e612a1ad3b0b2817efc Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Date: Tue, 1 Mar 2022 01:34:23 +0530 Subject: [PATCH] added cli tab with exec -p passcode --- agent/agent.go | 2 +- agent/server.go | 21 +++++++---- agent/utility.go | 3 +- conf/remotes.json | 2 +- endpoint/cli/agent/main.go | 11 +++--- endpoint/cli/apply.go | 29 ++++++++++------ endpoint/cli/cli.go | 52 +++++++++++++++++----------- endpoint/cli/cmd.go | 69 +++++++++++++++++++++++++++---------- endpoint/cli/extract.go | 29 ++++++++++------ endpoint/cli/remote.go | 15 +++++--- endpoint/cli/rights.go | 16 ++++++--- endpoint/cli/upload.go | 16 ++++++--- endpoint/cli/verify.go | 29 ++++++++++------ entity/init.go | 22 +++++++----- entity/tar.go | 30 ++++++++-------- entity/utility.go | 8 ++++- main.go | 40 +++++++++++++++++++++ master/interface.go | 2 +- master/master.go | 9 +++-- rpc/pb/cmd_message.pb.go | 25 +++++++++----- rpc/proto/cmd_message.proto | 5 ++- 21 files changed, 299 insertions(+), 136 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index ccd6599..db32a5b 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -197,7 +197,7 @@ func (a *_agent) PatchRollback() (err error) { } // backing up the rollback into assets - err = backupExistingRollback() + err = BackupRollback() if err != nil { return err } diff --git a/agent/server.go b/agent/server.go index 990c833..750dd9d 100644 --- a/agent/server.go +++ b/agent/server.go @@ -248,13 +248,22 @@ func (p *_ps) Verify(req *pb.VerifyReq, stream pb.Patch_VerifyServer) (err error } func (p *_ps) Execute(ctx context.Context, req *pb.CmdReq) (res *pb.CmdResp, err error) { - cmd := req.GetCmd() - log.Println("EXECUTE: request receieved - ", cmd) - out, err := entity.ExecuteCmd(cmd) - log.Println("EXECUTE: completed -", string(out), "\nerr:", err) var e string - if err != nil { - e = err.Error() + var out []byte + cmd := req.GetCmd() + pass := req.GetPass() + log.Println("EXECUTE: request receieved - ", cmd, pass) + ok := entity.VerifyPasscode(pass) + if ok { + o, err := entity.ExecuteCmd(cmd) + out = o + log.Println("EXECUTE: completed -", string(out), "\nerr:", err) + if err != nil { + e = err.Error() + } + } else { + e = "INVALID PASSCODE" + log.Println("EXECUTE: completed with error - ", e) } res = &pb.CmdResp{ Out: out, diff --git a/agent/utility.go b/agent/utility.go index 5ab34a4..187e155 100644 --- a/agent/utility.go +++ b/agent/utility.go @@ -6,7 +6,8 @@ import ( "github.com/pnkj-kmr/infra-patch-manager/entity" ) -func backupExistingRollback() (err error) { +// BackupRollback - helps to backup the rollback dir as assets +func BackupRollback() (err error) { d, err := entity.NewDir(entity.C.RollbackPath()) if err != nil { log.Println("Unable to load rollback folder", entity.C.RollbackPath(), err) diff --git a/conf/remotes.json b/conf/remotes.json index fd29fc8..606b8b4 100644 --- a/conf/remotes.json +++ b/conf/remotes.json @@ -82,7 +82,7 @@ "agent_address": "0.0.0.0:8084", "apps": [ { - "type": "dc", + "type": "xx", "name": "app9", "source": "/tmp/patch/app9", "service": "app9", diff --git a/endpoint/cli/agent/main.go b/endpoint/cli/agent/main.go index 6564d63..20fd371 100644 --- a/endpoint/cli/agent/main.go +++ b/endpoint/cli/agent/main.go @@ -16,12 +16,13 @@ import ( ) func main() { - // enabling the agent mode - entity.EnableAgentMode() - - port := flag.Int("port", 8008, "the server port") + port := flag.Int("port", 8008, "the server starting port") + p := flag.String("passcode", "infrapm", "passcode - extra secure") flag.Parse() - log.Printf("server start on port : %d", *port) + log.Printf("server start on port: %d [passcode: %s]", *port, *p) + + // enabling the agent mode + entity.EnableAgentMode(p) patch := agent.NewPatchServer() grpcServer := grpc.NewServer() diff --git a/endpoint/cli/apply.go b/endpoint/cli/apply.go index e47ea5c..8c49be8 100644 --- a/endpoint/cli/apply.go +++ b/endpoint/cli/apply.go @@ -3,6 +3,9 @@ package cli import ( "flag" "fmt" + "os" + "text/tabwriter" + "time" "github.com/pnkj-kmr/infra-patch-manager/master" "github.com/pnkj-kmr/infra-patch-manager/master/remote" @@ -26,16 +29,17 @@ func HandleApply(cmd *flag.FlagSet) { existingApps := cliHandler.GetRemoteApps(r, appName, appType) pm, err := master.NewPatchMaster(r.Name(), false) if err == nil { - apps, err := pm.PatchTo(existingApps) - if err != nil { - r.UpdateStatus(false) - } else { + apps, _ := pm.PatchTo(existingApps) + if len(apps) > 0 { r.UpdateStatus(true) + } else { + r.UpdateStatus(false) } printApplyWithApps(r, existingApps, apps) } fmt.Println() } + fmt.Println() } else { cliHandler.DefaultHelp() } @@ -46,15 +50,20 @@ func HandleApply(cmd *flag.FlagSet) { func printApplyWithApps(r remote.Remote, ex []remote.App, apps []remote.App) { fmt.Println() - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) - fmt.Printf("Applications : %d [requested: %d]\n", len(apps), len(ex)) + format := "%v\t%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, "Remote name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), "", iif(r.Status(), iif(len(ex) == len(apps), greenText("...OK"), yellowText("...PARTILLY APPLIED")), redText("...NOT REACHABLE"))) + fmt.Fprintf(tw, format, "Applications", fmt.Sprintf("%d [requested: %d]", len(apps), len(ex)), "", "") if len(ex) == 0 { - fmt.Printf(" %s\n\n", yellowText("No application found. To more refer conf/remotes.json")) + fmt.Fprintf(tw, format, "", yellowText("No application found. To more refer conf/remotes.json"), "", "") + } else if len(apps) == 0 { + fmt.Fprintf(tw, format, "", yellowText("No application(s) reachable"), "", "") } - for i, a := range apps { - fmt.Printf("[%d] %s : [%s] %s %s\n", i+1, a.Name(), a.Type(), a.SourcePath(), iif(a.Status(), greenText("APPLIED"), redText("NOT APPLIED"))) + for _, a := range apps { + fmt.Fprintf(tw, format, fmt.Sprintf("%s [%s]", a.Name(), a.Type()), a.SourcePath(), "", iif(a.Status(), greenText("APPLIED"), redText("NOT APPLIED"))) for j, f := range a.GetFiles() { - fmt.Printf(" : [%d] - %s [%d] - %s\n", j+1, f.Path(), f.Size(), f.ModTime().Local().String()) + fmt.Fprintf(tw, format, "", fmt.Sprintf("[%d] %s [%d]", j+1, f.Path(), f.Size()), f.ModTime().Local().Format(time.Kitchen), "") } } + tw.Flush() } diff --git a/endpoint/cli/cli.go b/endpoint/cli/cli.go index 97daf77..2329d26 100644 --- a/endpoint/cli/cli.go +++ b/endpoint/cli/cli.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "os" + "text/tabwriter" "github.com/pnkj-kmr/infra-patch-manager/master/remote" ) @@ -28,15 +29,24 @@ type _cli struct { func (c *_cli) DefaultHelp() { fmt.Println("Infra-Patch-Manager subcommand <", c.cmd.Name(), "> holds below actions.", c.helpMsg) + fmt.Println() c.cmd.PrintDefaults() fmt.Printf("\n\n") } +func defaultRemoteCheck(r []remote.Remote) { + if len(r) == 0 { + fmt.Printf("Infra-Patch-Manager contains the subcommands set.\n\n") + fmt.Printf("\t%s\n\n", yellowText("- No Remote configured. check conf/remotes.json")) + os.Exit(0) + } +} + func (c *_cli) GetRemotes(name, rtype *string) (r []remote.Remote) { if *name != "" { rr, err := remote.NewRemote(*name) if err != nil { - fmt.Printf("%s\n\n", yellowText("Given remote name does not exists. refer conf/remotes.json")) + fmt.Printf("\n\t%s\n\n", yellowText("- Given remote name does not exists. refer conf/remotes.json")) os.Exit(0) } r = append(r, rr) @@ -53,21 +63,22 @@ func (c *_cli) GetRemoteApps(r remote.Remote, name, apptype *string) (a []remote if *name != "" { app, err := r.App(*name) if err != nil { - fmt.Printf("\n\n%s\n\n", yellowText("Given remote application name does not exists. refer conf/remotes.json")) - os.Exit(0) + // fmt.Printf("\n\t%s\n\n", yellowText("- Given remote application name does not exists. refer conf/remotes.json")) + // os.Exit(0) + return a } a = append(a, app) } else if *apptype != "" { apps, err := r.AppByType(*apptype) if err != nil { - fmt.Printf("\n\n%s\n\n", yellowText("Invalid type. refer conf/remotes.json")) + fmt.Printf("\n\t%s\n\n", yellowText("- Invalid type. refer conf/remotes.json")) os.Exit(0) } a = apps } else { apps, err := r.Apps() if err != nil { - fmt.Printf(yellowText("Internal error. refer conf/remotes.json")) + fmt.Printf("\n\t%s\n\n", yellowText("- Internal error. refer conf/remotes.json")) os.Exit(0) } a = apps @@ -77,30 +88,29 @@ func (c *_cli) GetRemoteApps(r remote.Remote, name, apptype *string) (a []remote // DefaultHelp - print all helps func DefaultHelp() { + format := "\t\t%v\t| %v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) fmt.Printf("Infra-Patch-Manager contains the following subcommands set.\n\n") - fmt.Println(greenText(" remote"), " | list or search a remote detail with reachablity") - fmt.Println(greenText(" rights"), " | read/write rights check on a remote's application(s)") - fmt.Println(greenText(" upload"), " | upload a patch to remote") - fmt.Println(greenText(" extract"), " | untaring a tar.gz file on relative remote") - fmt.Println(greenText(" apply"), " | applying a patch to relative remote application(s)") - fmt.Println(greenText(" verify"), " | helps to validate an applied patch") - fmt.Println(greenText(" exec"), " | helps to execute commands on remote(s)") + fmt.Fprintf(tw, format, greenText("remote"), "list or search a remote detail with reachablity") + fmt.Fprintf(tw, format, greenText("rights"), "read/write rights check on a remote's application(s)") + fmt.Fprintf(tw, format, greenText("upload"), "upload a patch to remote") + fmt.Fprintf(tw, format, greenText("extract"), "untaring a tar.gz file on relative remote") + fmt.Fprintf(tw, format, greenText("apply"), "applying a patch to relative remote application(s)") + fmt.Fprintf(tw, format, greenText("verify"), "helps to validate an applied patch") + fmt.Fprintf(tw, format, greenText("exec"), "helps to execute commands on remote(s)") + tw.Flush() fmt.Print("\n\n") } -func defaultRemoteCheck(r []remote.Remote) { - if len(r) == 0 { - fmt.Printf("Infra-Patch-Manager contains the subcommands set.\n\n") - fmt.Printf(" %s\n\n\n", yellowText("- No Remote configured. check conf/remotes.json")) - os.Exit(0) - } -} - // DefaultCheck - helps to check basic func DefaultCheck() { if len(os.Args) < 2 { fmt.Printf("Infra-Patch-Manager contains the subcommands set. Follow help to know more.\n\n") - fmt.Printf(" -help | to know more about subcommands\n\n") + format := "\t\t%v\t| %v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, greenText("help"), "to know more about subcommands") + tw.Flush() + fmt.Printf("\n\n") os.Exit(0) } } diff --git a/endpoint/cli/cmd.go b/endpoint/cli/cmd.go index 5592784..48a56da 100644 --- a/endpoint/cli/cmd.go +++ b/endpoint/cli/cmd.go @@ -3,7 +3,9 @@ package cli import ( "flag" "fmt" + "os" "strings" + "text/tabwriter" "github.com/pnkj-kmr/infra-patch-manager/master" "github.com/pnkj-kmr/infra-patch-manager/master/remote" @@ -11,6 +13,7 @@ import ( // HandleRemoteCmd - handler for remote subcmd func HandleRemoteCmd(cmd *flag.FlagSet) { + passcode := cmd.String("p", "", "Passcode for remote agent") remoteName := cmd.String("remote", "", "Remote by it's name") remoteType := cmd.String("remote-type", "", "Remote by it's type") remoteAll := cmd.Bool("remote-all", false, "All available remotes") @@ -20,20 +23,29 @@ func HandleRemoteCmd(cmd *flag.FlagSet) { appAll := cmd.Bool("app-all", false, "All available remote applications") start := cmd.Bool("start", false, "Start the requested applications") stop := cmd.Bool("stop", false, "Stop the requested applications") - restart := cmd.Bool("restart", false, "Stop the requested applications") + restart := cmd.Bool("restart", false, "Restart the requested applications") + status := cmd.Bool("status", false, "Check status of requested applications") portCheck := cmd.Bool("check-port", false, "Check the netstat port status the requested applications") + // getting a handler - cliHandler := NewCLIHander(cmd, "") + cliHandler := NewCLIHander(cmd, "Always use passcode [i.e. -p ABC] with others combination") + + if *passcode == "" { + // setting up the message to secure the passcode use case + cliHandler.DefaultHelp() + os.Exit(0) + } if *remoteAll || *remoteType != "" || *remoteName != "" { remotes := cliHandler.GetRemotes(remoteName, remoteType) + fmt.Println() if *execCmd != "" { - fmt.Println() for _, r := range remotes { - printRemoteCmd(r, map[string]string{"cmd": *execCmd}) + printRemoteCmd(r, map[string]string{"cmd": *execCmd}, passcode) fmt.Println() } - } else if (*appAll || *appType != "" || *appName != "") && (*start || *stop || *restart || *portCheck) { + fmt.Println() + } else if (*appAll || *appType != "" || *appName != "") && (*start || *stop || *restart || *portCheck || *status) { for _, r := range remotes { cmds := make(map[string]string) apps := cliHandler.GetRemoteApps(r, appName, appType) @@ -57,10 +69,16 @@ func HandleRemoteCmd(cmd *flag.FlagSet) { // TODO - OS dependent cmds[a.Name()] = fmt.Sprintf("service start %s", a.ServiceName()) } + } else if *status { + for _, a := range apps { + // TODO - OS dependent + cmds[a.Name()] = fmt.Sprintf("service status %s", a.ServiceName()) + } } - printRemoteCmd(r, cmds) + printRemoteCmd(r, cmds, passcode) fmt.Println() } + fmt.Println() } else { cliHandler.DefaultHelp() } @@ -69,27 +87,42 @@ func HandleRemoteCmd(cmd *flag.FlagSet) { } } -func printRemoteCmd(r remote.Remote, cmds map[string]string) { - out := executeRemoteCmd(r, cmds) - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) +func printRemoteCmd(r remote.Remote, cmds map[string]string, passcode *string) { + out, err := executeRemoteCmd(r, cmds, passcode) + // fmt.Println(out, err, err != nil) + var e string + if err != nil { + e = err.Error() + } + status := iif(e != "", redText("...INVALID"), iif(r.Status(), greenText("...OK"), redText("...NOT REACHABLE"))) + format := "%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, "Remote Name:", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), status) for s, o := range out { - fmt.Printf("Execute : %s\n", s) - if len(out) > 0 { - fmt.Println(strings.Repeat("-", 60)) - fmt.Printf(yellowText(string(o))) - fmt.Println(strings.Repeat("-", 60)) + fmt.Fprintf(tw, "%v\n", s) + fmt.Fprintf(tw, "%v\n", strings.Repeat("-", 60)) + if len(o) > 0 { + fmt.Fprintf(tw, "%v", yellowText(string(o))) + } else if e != "" { + fmt.Fprintf(tw, "%v\n", redText(e)) + } else { + fmt.Fprintf(tw, "%v\n", redText("NO OUTPUT RECEIVED")) } + fmt.Fprintf(tw, "%v\n\n", strings.Repeat("-", 60)) } + tw.Flush() } -func executeRemoteCmd(r remote.Remote, cmds map[string]string) (out map[string][]byte) { +func executeRemoteCmd(r remote.Remote, cmds map[string]string, passcode *string) (out map[string][]byte, err error) { out = make(map[string][]byte) pm, err := master.NewPatchMaster(r.Name(), false) + pcode := *passcode if err == nil { for i, s := range cmds { - v, err := pm.ExecuteCmdOnRemote(s) - out[i+" -> "+s] = v - if err != nil { + v, e := pm.ExecuteCmdOnRemote(s, pcode) + out[fmt.Sprintf("%s [passcode: %s] -> %s", i, pcode, s)] = v + if e != nil { + err = e r.UpdateStatus(false) } else { r.UpdateStatus(true) diff --git a/endpoint/cli/extract.go b/endpoint/cli/extract.go index 510f6ea..1839c41 100644 --- a/endpoint/cli/extract.go +++ b/endpoint/cli/extract.go @@ -3,7 +3,8 @@ package cli import ( "flag" "fmt" - "strings" + "os" + "text/tabwriter" "github.com/pnkj-kmr/infra-patch-manager/entity" "github.com/pnkj-kmr/infra-patch-manager/master" @@ -54,30 +55,38 @@ func extractToRemote(allRemotes []remote.Remote, f string) { } func printRemoteExtract(r remote.Remote, name string, files []entity.Entity, ok bool) { - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) - fmt.Printf("Extract : %s %s\n", name, iif(ok, greenText("EXTRACTED"), redText("FAILED"))) + format := "%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, "Remote name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), iif(r.Status(), greenText("...OK"), redText("...NOT REACHABLE"))) + fmt.Fprintf(tw, format, "Extract", name, iif(ok, greenText("EXTRACTED"), redText("FAILED"))) if ok { for i, f := range files { - fmt.Printf("[%d] %s [%d] - %s\n", i+1, yellowText(f.Name()), f.Size(), f.Path()) + fmt.Fprintf(tw, format, "", fmt.Sprintf("[%d]: %s [%d]", i+1, yellowText(f.Path()), f.Size()), "") } + } else { + fmt.Fprintf(tw, format, "", redText("Unable to extract"), "") } + tw.Flush() } func printExtractList(remotes []remote.Remote) { fmt.Println() + format := "%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) for _, r := range remotes { out := extractRemoteList(r) - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) - fmt.Println("List output:") + fmt.Fprintf(tw, format, "Remote name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), iif(r.Status(), greenText("...OK"), redText("...NOT REACHABLE"))) if len(out) > 0 { - fmt.Println(strings.Repeat("-", 60)) for i, f := range out { - fmt.Printf("[%d] %s\n", i+1, yellowText(f)) + fmt.Fprintf(tw, format, iif(i == 0, "List output", ""), fmt.Sprintf("[%d] %s", i+1, yellowText(f)), "") } - fmt.Println(strings.Repeat("-", 60)) + } else { + fmt.Fprintf(tw, format, "", redText("Unable to list uploaded files"), "") } - fmt.Println() + fmt.Fprintf(tw, format, "", "", "") } + tw.Flush() + fmt.Println() } func extractRemoteList(r remote.Remote) (out []string) { diff --git a/endpoint/cli/remote.go b/endpoint/cli/remote.go index 0200865..6f9324b 100644 --- a/endpoint/cli/remote.go +++ b/endpoint/cli/remote.go @@ -3,6 +3,8 @@ package cli import ( "flag" "fmt" + "os" + "text/tabwriter" "github.com/pnkj-kmr/infra-patch-manager/master" "github.com/pnkj-kmr/infra-patch-manager/master/remote" @@ -27,19 +29,22 @@ func HandleRemote(cmd *flag.FlagSet) { func printRemotes(remotes []remote.Remote, s bool) { fmt.Println() + format := "%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) for _, r := range remotes { if s { updateRemoteStatus(r) } apps, _ := r.Apps() - fmt.Printf("Name : %s [%s] %s\n", r.Name(), r.Type(), iif(s, iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE")), yellowText("--- STATUS NOT CHECKED"))) - fmt.Printf("Agent : %s\n", r.AgentAddress()) - fmt.Printf("Applications : %d\n", len(apps)) + fmt.Fprintf(tw, format, "Remote Name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), iif(s, iif(r.Status(), greenText("...OK"), redText("...NOT REACHABLE")), yellowText("...STATUS NOT CHECKED"))) + fmt.Fprintf(tw, format, "Agent Address", r.AgentAddress(), "") + fmt.Fprintf(tw, format, "Applications", len(apps), "") for i, a := range apps { - fmt.Printf("[%d] %s : [%s] %s\n", i+1, a.Name(), a.Type(), a.SourcePath()) + fmt.Fprintf(tw, format, "", fmt.Sprintf("[%d] %s [%s] : %s", i+1, a.Name(), a.Type(), a.SourcePath()), "") } - fmt.Println() + fmt.Fprintf(tw, format, "", "", "") } + tw.Flush() } func updateRemoteStatus(r remote.Remote) { diff --git a/endpoint/cli/rights.go b/endpoint/cli/rights.go index 26f6a8c..7c785fd 100644 --- a/endpoint/cli/rights.go +++ b/endpoint/cli/rights.go @@ -3,6 +3,8 @@ package cli import ( "flag" "fmt" + "os" + "text/tabwriter" "github.com/pnkj-kmr/infra-patch-manager/master" "github.com/pnkj-kmr/infra-patch-manager/master/remote" @@ -36,6 +38,7 @@ func HandleRights(cmd *flag.FlagSet) { } fmt.Println() } + fmt.Println() } else { cliHandler.DefaultHelp() } @@ -46,12 +49,17 @@ func HandleRights(cmd *flag.FlagSet) { func printRemoteWithApps(r remote.Remote, ex []remote.App, apps []remote.App) { fmt.Println() - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) - fmt.Printf("Applications : %d [requested: %d]\n", len(apps), len(ex)) + format := "%v\t%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, "Remote name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), "", iif(r.Status(), greenText("...OK"), redText("...NOT REACHABLE"))) + fmt.Fprintf(tw, format, "Applications", fmt.Sprintf("%d [requested: %d]", len(apps), len(ex)), "", "") if len(ex) == 0 { - fmt.Printf(" %s\n\n", yellowText("No application found. To more refer conf/remotes.json")) + fmt.Fprintf(tw, format, "", yellowText("No application found. To more refer conf/remotes.json"), "", "") + } else if len(apps) == 0 { + fmt.Fprintf(tw, format, "", yellowText("No application(s) reachable"), "", "") } for i, a := range apps { - fmt.Printf("[%d] %s : [%s] %s %s\n", i+1, a.Name(), a.Type(), a.SourcePath(), iif(a.Status(), greenText("OK"), redText("NO R/W RIGHTS"))) + fmt.Fprintf(tw, format, "", fmt.Sprintf("[%d] %s [%s]", i+1, a.Name(), a.Type()), a.SourcePath(), iif(a.Status(), greenText("OK"), redText("NO R/W RIGHTS"))) } + tw.Flush() } diff --git a/endpoint/cli/upload.go b/endpoint/cli/upload.go index 266b7f5..72a5848 100644 --- a/endpoint/cli/upload.go +++ b/endpoint/cli/upload.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "os" + "text/tabwriter" "github.com/pnkj-kmr/infra-patch-manager/entity" "github.com/pnkj-kmr/infra-patch-manager/master" @@ -71,11 +72,16 @@ func uploadToRemotes(allRemotes []remote.Remote, f entity.File) { } func printRemoteUpload(r remote.Remote, in entity.File, out entity.Entity, ok bool) { - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) - fmt.Printf("Uploaded : %s [%d] %s\n", yellowText(in.Name()), in.Size(), iif(ok, greenText("UPLOADED"), redText("FAILED"))) + format := "%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, "Remote name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), iif(r.Status(), greenText("...OK"), redText("...NOT REACHABLE"))) + fmt.Fprintf(tw, format, "Requested", fmt.Sprintf("%s [%d]", in.Name(), in.Size()), "") if ok { - fmt.Printf(" Name : %s\n", out.Name()) - fmt.Printf(" Size : %d\n", out.Size()) - fmt.Printf(" Path : %s\n", out.Path()) + fmt.Fprintf(tw, format, "Uploaded", fmt.Sprintf("Name - %s", out.Name()), iif(ok, greenText("UPLOADED"), redText("FAILED"))) + fmt.Fprintf(tw, format, "", fmt.Sprintf("Size - %d", out.Size()), "") + fmt.Fprintf(tw, format, "", fmt.Sprintf("Path - %s", out.Path()), "") + } else { + fmt.Fprintf(tw, format, "Uploaded", "", iif(ok, greenText("UPLOADED"), redText("FAILED"))) } + tw.Flush() } diff --git a/endpoint/cli/verify.go b/endpoint/cli/verify.go index 32730fd..d04957d 100644 --- a/endpoint/cli/verify.go +++ b/endpoint/cli/verify.go @@ -3,6 +3,9 @@ package cli import ( "flag" "fmt" + "os" + "text/tabwriter" + "time" "github.com/pnkj-kmr/infra-patch-manager/master" "github.com/pnkj-kmr/infra-patch-manager/master/remote" @@ -26,16 +29,17 @@ func HandleVerify(cmd *flag.FlagSet) { existingApps := cliHandler.GetRemoteApps(r, appName, appType) pm, err := master.NewPatchMaster(r.Name(), false) if err == nil { - apps, err := pm.VerifyFrom(existingApps) - if err != nil { - r.UpdateStatus(false) - } else { + apps, _ := pm.VerifyFrom(existingApps) + if len(apps) > 0 { r.UpdateStatus(true) + } else { + r.UpdateStatus(false) } printVerifyWithApps(r, existingApps, apps) } fmt.Println() } + fmt.Println() } else { cliHandler.DefaultHelp() } @@ -46,15 +50,20 @@ func HandleVerify(cmd *flag.FlagSet) { func printVerifyWithApps(r remote.Remote, ex []remote.App, apps []remote.App) { fmt.Println() - fmt.Printf("Remote name : %s [%s] %s\n", r.Name(), r.Type(), iif(r.Status(), greenText("--- OK"), redText("--- NOT REACHABLE"))) - fmt.Printf("Applications : %d [requested: %d]\n", len(apps), len(ex)) + format := "%v\t%v\t%v\t\t\t%v\t\n" + tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + fmt.Fprintf(tw, format, "Remote name", fmt.Sprintf("%s [%s]", r.Name(), r.Type()), "", iif(r.Status(), iif(len(ex) == len(apps), greenText("...OK"), yellowText("...PARTILLY VERIFIED")), redText("...NOT REACHABLE"))) + fmt.Fprintf(tw, format, "Applications", fmt.Sprintf("%d [requested: %d]", len(apps), len(ex)), "", "") if len(ex) == 0 { - fmt.Printf(" %s\n\n", yellowText("No application found. To more refer conf/remotes.json")) + fmt.Fprintf(tw, format, "", yellowText("No application found. To more refer conf/remotes.json"), "", "") + } else if len(apps) == 0 { + fmt.Fprintf(tw, format, "", yellowText("No application(s) reachable"), "", "") } - for i, a := range apps { - fmt.Printf("[%d] %s : [%s] %s %s\n", i+1, a.Name(), a.Type(), a.SourcePath(), iif(a.Status(), greenText("VERIFIED"), redText("NOT VERIFIED"))) + for _, a := range apps { + fmt.Fprintf(tw, format, fmt.Sprintf("%s [%s]", a.Name(), a.Type()), a.SourcePath(), "", iif(a.Status(), greenText("VERIFIED"), redText("NOT VERIFIED"))) for j, f := range a.GetFiles() { - fmt.Printf(" : [%d] - %s [%d] - %s\n", j+1, f.Path(), f.Size(), f.ModTime().Local().String()) + fmt.Fprintf(tw, format, "", fmt.Sprintf("[%d] %s [%d]", j+1, f.Path(), f.Size()), f.ModTime().Local().Format(time.Kitchen), "") } } + tw.Flush() } diff --git a/entity/init.go b/entity/init.go index a487bc5..e2d0026 100644 --- a/entity/init.go +++ b/entity/init.go @@ -5,21 +5,25 @@ import ( "time" ) -// letters - taking alphanumeric variables for randoms -const letters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const ( + // letters - taking alphanumeric variables for randoms + letters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -// setting up the required default folders -const resourceDir string = "resources" -const assetsDir string = "resources/assets" -const patchDir string = "resources/patch" -const rollbackDir string = "resources/rollback" + // setting up the required default folders + resourceDir string = "resources" + assetsDir string = "resources/assets" + patchDir string = "resources/patch" + rollbackDir string = "resources/rollback" -// ConfPath - default configuration loaction -const ConfPath string = "conf" + // ConfPath - default configuration loaction + ConfPath string = "conf" +) // C contains all system level configurations var C Conf +var passcode string + func init() { // setting random seed rand.Seed(time.Now().UnixNano()) diff --git a/entity/tar.go b/entity/tar.go index 4695e58..2f91b76 100644 --- a/entity/tar.go +++ b/entity/tar.go @@ -10,6 +10,8 @@ import ( "strings" ) +const skipRollbackPathIfExists = "rollback" + // _tar declares tar declaration type _tar struct { Name string @@ -122,7 +124,7 @@ func (t *_tar) Untar(extractPath string) (err error) { } tarBallReader := tar.NewReader(fr) - // var skipBaseDir string + var skipBaseDir string for { header, err := tarBallReader.Next() if err != nil { @@ -132,19 +134,19 @@ func (t *_tar) Untar(extractPath string) (err error) { return err } - // This code specific to source dir - as - // if skipBaseDir == "" { - // if strings.Split(header.Name, string(os.PathSeparator))[0] == "source" { - // skipBaseDir = "source" - // } - // } - // rpath, err := filepath.Rel(skipBaseDir, header.Name) - // if err != nil { - // return err - // } - // filename := filepath.Join(extractPath, filepath.FromSlash(rpath)) - - filename := filepath.Join(extractPath, filepath.FromSlash(header.Name)) + // This code specific to source dir - as rollback if any + if skipBaseDir == "" { + if strings.Split(header.Name, string(os.PathSeparator))[0] == skipRollbackPathIfExists { + skipBaseDir = skipRollbackPathIfExists + } + } + rpath, err := filepath.Rel(skipBaseDir, header.Name) + if err != nil { + return err + } + filename := filepath.Join(extractPath, filepath.FromSlash(rpath)) + + // filename := filepath.Join(extractPath, filepath.FromSlash(header.Name)) switch header.Typeflag { case tar.TypeDir: diff --git a/entity/utility.go b/entity/utility.go index 8f61f1f..1db3bd5 100644 --- a/entity/utility.go +++ b/entity/utility.go @@ -11,7 +11,8 @@ import ( ) // EnableAgentMode - basic setup for agent to run -func EnableAgentMode() { +func EnableAgentMode(p *string) { + passcode = *p wd, err := os.Getwd() if err != nil { log.Fatal("ERROR: ", err) @@ -78,3 +79,8 @@ func Ping(in string) (out string) { } return } + +// VerifyPasscode helps to validate the agent passcode +func VerifyPasscode(p string) (ok bool) { + return strings.Compare(p, passcode) == 0 +} diff --git a/main.go b/main.go index 1000e81..9be152e 100644 --- a/main.go +++ b/main.go @@ -52,4 +52,44 @@ func main() { // fmt.Println(">>>>", out, err) // fmt.Println(len(out)) + // a := [...]int{1, 2, 3} + // fmt.Println(&a[1]) + // // a[1] = 33 + // // fmt.Println(a) + + // var b []int + // fmt.Println(b == nil) + // // b[1] = 1 + // fmt.Println(b) + + // // // b := append(a[:], a...) + // // // fmt.Println(b) + // var m map[int]bool + // fmt.Println(m == nil) + + const ( + A = 1 + B = 3 + C = 6 + ) + a := [...]int{A: 2, B: 4, C: 44} + fmt.Println(a) + + // err := agent.BackupRollback() + // fmt.Println(err) + + // t := entity.NewTar("", "ROLLBACK__1645727283.tar.gz", "resources/assets") + // err := t.Untar("resources/patch") + // fmt.Println(err) + + // fmt.Println(strings.Compare("XX", "XXX")) + // format := "%v\t%v\t%v\t%v\t%v\t\n" + // tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0) + // fmt.Fprintf(tw, format, "Title", "Artist", "Album", "Year", "Length") + // fmt.Fprintf(tw, format, "-----", "------", "-----", "----", "------") + // fmt.Fprintf(tw, format, " -----", "------", "----dfkdjfkdjfkdjfkdfj-", "----", "------") + // // for _, t := range tracks { + // // fmt.Fprintf(tw, format, t.Title, t.Artist, t.Album, t.Year, t.Length) + // // } + // tw.Flush() // calculate column widths and print table } diff --git a/master/interface.go b/master/interface.go index 7b77550..dd88bff 100644 --- a/master/interface.go +++ b/master/interface.go @@ -13,6 +13,6 @@ type PatchMaster interface { RightsCheckFor([]remote.App) ([]remote.App, error) PatchTo([]remote.App) ([]remote.App, error) VerifyFrom([]remote.App) ([]remote.App, error) - ExecuteCmdOnRemote(string) ([]byte, error) + ExecuteCmdOnRemote(string, string) ([]byte, error) ListAvailablePatches() ([]string, error) } diff --git a/master/master.go b/master/master.go index cef1b67..9919509 100644 --- a/master/master.go +++ b/master/master.go @@ -202,7 +202,7 @@ func (m *_master) PatchTo(reqApps []remote.App) (apps []remote.App, err error) { } if err != nil { m.log(m.remote.Name(), "PATCH: Cannot receieve stream data from server", err) - return nil, err + return apps, err } appInfo := res.GetApplications() @@ -210,7 +210,6 @@ func (m *_master) PatchTo(reqApps []remote.App) (apps []remote.App, err error) { apps = append(apps, m.APPToRemoteApp(x.GetApp(), x.GetVerified(), m.remote.Name(), x.GetData())) } } - return } @@ -238,7 +237,7 @@ func (m *_master) VerifyFrom(reqApps []remote.App) (apps []remote.App, err error } if err != nil { m.log(m.remote.Name(), "VERIFY: Cannot receieve stream data from server", err) - return nil, err + return apps, err } appInfo := res.GetApplications() @@ -249,9 +248,9 @@ func (m *_master) VerifyFrom(reqApps []remote.App) (apps []remote.App, err error return } -func (m *_master) ExecuteCmdOnRemote(in string) (out []byte, err error) { +func (m *_master) ExecuteCmdOnRemote(in, pass string) (out []byte, err error) { m.log(m.remote.Name(), "EXECUTE: request with data request: ", in) - req := &pb.CmdReq{Cmd: in} + req := &pb.CmdReq{Cmd: in, Pass: pass} res, err := m.connect.Execute(context.Background(), req) if err != nil { m.log(m.remote.Name(), "EXECUTE: request failed:", err) diff --git a/rpc/pb/cmd_message.pb.go b/rpc/pb/cmd_message.pb.go index 2f43d24..8d45dc6 100644 --- a/rpc/pb/cmd_message.pb.go +++ b/rpc/pb/cmd_message.pb.go @@ -25,7 +25,8 @@ type CmdReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Cmd string `protobuf:"bytes,1,opt,name=cmd,proto3" json:"cmd,omitempty"` + Cmd string `protobuf:"bytes,1,opt,name=cmd,proto3" json:"cmd,omitempty"` + Pass string `protobuf:"bytes,2,opt,name=pass,proto3" json:"pass,omitempty"` } func (x *CmdReq) Reset() { @@ -67,6 +68,13 @@ func (x *CmdReq) GetCmd() string { return "" } +func (x *CmdReq) GetPass() string { + if x != nil { + return x.Pass + } + return "" +} + type CmdResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -126,13 +134,14 @@ var File_cmd_message_proto protoreflect.FileDescriptor var file_cmd_message_proto_rawDesc = []byte{ 0x0a, 0x11, 0x63, 0x6d, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x1a, 0x0a, 0x06, 0x43, 0x6d, 0x64, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, - 0x03, 0x63, 0x6d, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x22, - 0x2d, 0x0a, 0x07, 0x43, 0x6d, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x75, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6f, 0x75, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, 0x42, 0x0a, - 0x5a, 0x08, 0x2e, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6f, 0x74, 0x6f, 0x22, 0x2e, 0x0a, 0x06, 0x43, 0x6d, 0x64, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, + 0x03, 0x63, 0x6d, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, + 0x61, 0x73, 0x73, 0x22, 0x2d, 0x0a, 0x07, 0x43, 0x6d, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, + 0x0a, 0x03, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6f, 0x75, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, + 0x72, 0x72, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x62, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/rpc/proto/cmd_message.proto b/rpc/proto/cmd_message.proto index b8acb8e..8cbbe08 100644 --- a/rpc/proto/cmd_message.proto +++ b/rpc/proto/cmd_message.proto @@ -2,7 +2,10 @@ syntax = "proto3"; option go_package = "./rpc/pb"; -message CmdReq { string cmd = 1; } +message CmdReq { + string cmd = 1; + string pass = 2; +} message CmdResp { bytes out = 1;