From c5fac7bbecde46df7030076831c78a91f8d8cc43 Mon Sep 17 00:00:00 2001
From: Malte Bauch <malte.bauch@stud.h-da.de>
Date: Wed, 6 Sep 2023 09:06:16 +0000
Subject: [PATCH] Resolve "PostRun function in cli does not get called if an
 error is thrown"

Update all CLI commands to use `Run` (no error returning) instead of `RunE` (run with returning errors), since we already had an error logging through `pterm`. Prompt mode does check now for suggestions if the last cached suggestion is the right one for the current command.

See merge request danet/gosdn!540
---
 cli/cmd/changeCommit.go                  |  2 +
 cli/cmd/changeConfirm.go                 |  2 +
 cli/cmd/changeGet.go                     |  1 +
 cli/cmd/changeList.go                    | 11 ++-
 cli/cmd/list.go                          | 10 +--
 cli/cmd/login.go                         |  9 ++-
 cli/cmd/logout.go                        |  8 +--
 cli/cmd/networkElementCreate.go          | 10 ++-
 cli/cmd/networkElementList.go            |  8 +--
 cli/cmd/networkElementPathDelete.go      |  9 ++-
 cli/cmd/networkElementPathGet.go         |  7 +-
 cli/cmd/networkElementPathGetIntended.go |  8 +--
 cli/cmd/networkElementPathSet.go         | 20 +++---
 cli/cmd/networkElementRemove.go          |  7 +-
 cli/cmd/networkElementShow.go            |  6 +-
 cli/cmd/networkElementSubscribe.go       |  8 +--
 cli/cmd/pluginList.go                    |  8 +--
 cli/cmd/pndCreate.go                     |  6 +-
 cli/cmd/pndGet.go                        |  5 +-
 cli/cmd/pndList.go                       |  8 +--
 cli/cmd/pndRemove.go                     |  7 +-
 cli/cmd/pndUse.go                        |  9 ++-
 cli/cmd/prompt.go                        | 87 +++++++++++++++++-------
 cli/cmd/userCreate.go                    |  8 +--
 cli/cmd/userDelete.go                    |  8 +--
 cli/cmd/userGet.go                       |  8 +--
 cli/cmd/userGetAll.go                    |  8 +--
 cli/cmd/userUpdate.go                    | 11 +--
 go.sum                                   |  4 --
 29 files changed, 159 insertions(+), 144 deletions(-)

diff --git a/cli/cmd/changeCommit.go b/cli/cmd/changeCommit.go
index 49e035eed..406da9e9c 100644
--- a/cli/cmd/changeCommit.go
+++ b/cli/cmd/changeCommit.go
@@ -49,10 +49,12 @@ Change UUID must be specified as positional argument.`,
 		cuid, err := uuid.Parse(args[0])
 		if err != nil {
 			pterm.Error.Println(err)
+			return
 		}
 		resp, err := pndAdapter.Commit(createContextWithAuthorization(), cuid)
 		if err != nil {
 			pterm.Error.Println(err)
+			return
 		}
 		for _, r := range resp.GetResponses() {
 			pterm.Info.Printfln("Change with ID: %s has been committed.", r.GetId())
diff --git a/cli/cmd/changeConfirm.go b/cli/cmd/changeConfirm.go
index 249738c6e..41550ede0 100644
--- a/cli/cmd/changeConfirm.go
+++ b/cli/cmd/changeConfirm.go
@@ -49,11 +49,13 @@ Change UUID must be specified as positional argument`,
 		cuid, err := uuid.Parse(args[0])
 		if err != nil {
 			pterm.Error.Println(err)
+			return
 		}
 
 		resp, err := pndAdapter.Confirm(createContextWithAuthorization(), cuid)
 		if err != nil {
 			pterm.Error.Println(err)
+			return
 		}
 		for _, r := range resp.GetResponses() {
 			pterm.Info.Printfln("Change with ID: %s has been confirmed.", r.GetId())
diff --git a/cli/cmd/changeGet.go b/cli/cmd/changeGet.go
index a7c1aa331..ff8e3c3b4 100644
--- a/cli/cmd/changeGet.go
+++ b/cli/cmd/changeGet.go
@@ -49,6 +49,7 @@ var getCmd = &cobra.Command{
 		changes, err := pndAdapter.GetChange(createContextWithAuthorization(), args[0])
 		if err != nil {
 			pterm.Error.Println(err)
+			return
 		}
 		for _, c := range changes.GetChange() {
 			title := pterm.Sprintf("Change with ID: %s", c.GetId())
diff --git a/cli/cmd/changeList.go b/cli/cmd/changeList.go
index d5b0ea11e..2b1a57501 100644
--- a/cli/cmd/changeList.go
+++ b/cli/cmd/changeList.go
@@ -43,17 +43,17 @@ var changeListCmd = &cobra.Command{
 	Short:   "list all changes",
 	Long:    `Lists all configuration changes with their UUIDs.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Process change list request")
 		committed, err := pndAdapter.CommittedChanges(createContextWithAuthorization())
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 		pending, err := pndAdapter.PendingChanges(createContextWithAuthorization())
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		// TODO: maybe we want to return more information about changes? E.g.,
@@ -70,10 +70,9 @@ var changeListCmd = &cobra.Command{
 		spinner.Success()
 		err = pterm.DefaultTable.WithHasHeader().WithData(data).Render()
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/list.go b/cli/cmd/list.go
index 7ff31bcbf..2e476d4e7 100644
--- a/cli/cmd/list.go
+++ b/cli/cmd/list.go
@@ -33,6 +33,7 @@ package cmd
 
 import (
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
+	"github.com/pterm/pterm"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -44,16 +45,18 @@ var listCmd = &cobra.Command{
 	Short:   "List all PNDs, SBIs and MNEs on the controller",
 	Long:    `List all PNDs, SBIs and MNEs on the controller.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		addr := viper.GetString("controllerApiEndpoint")
 		resp, err := api.GetIds(createContextWithAuthorization(), addr)
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 		for i, pnd := range resp {
 			mneResp, err := api.GetFlattenedNetworkElements(createContextWithAuthorization(), addr, pnd.GetId())
 			if err != nil {
-				return err
+				pterm.Error.Println(err)
+				return
 			}
 			log.Infof("PND %v: name: %v, uuid: %v", i+1, pnd.Name, pnd.Id)
 			for k, mne := range mneResp.GetMne() {
@@ -61,7 +64,6 @@ var listCmd = &cobra.Command{
 				log.Infof("    Plugin %v: uuid: %v", k+1, mne.GetPid())
 			}
 		}
-		return nil
 	},
 }
 
diff --git a/cli/cmd/login.go b/cli/cmd/login.go
index ac210be64..babf01ee8 100644
--- a/cli/cmd/login.go
+++ b/cli/cmd/login.go
@@ -47,12 +47,13 @@ var loginCmd = &cobra.Command{
 	Long: `Logs the user in to allow further actions on the controller.
     User credentials need to be provided in the body`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Login attempt for user: ", nbUserName)
 
 		if controllerAPIEndpoint != "" {
 			if err := viper.WriteConfig(); err != nil {
 				pterm.Error.Println("Could not write config:", err)
+				return
 			}
 			pterm.Info.Println("New controller address: ", viper.GetString("controllerAPIEndpoint"))
 		}
@@ -66,7 +67,7 @@ var loginCmd = &cobra.Command{
 		resp, err := api.Login(context.TODO(), viper.GetString("controllerAPIEndpoint"), nbUserName, nbUserPwd)
 		if err != nil {
 			spinner.Fail("Login failed: ", err)
-			return err
+			return
 		}
 
 		spinner.Success("Authentication for ", nbUserName, " was successful.")
@@ -78,12 +79,10 @@ var loginCmd = &cobra.Command{
 		err = viper.WriteConfig()
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		pterm.Info.Println("Authentication-User-Token:", userToken)
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/logout.go b/cli/cmd/logout.go
index 997b035aa..68bc8a739 100644
--- a/cli/cmd/logout.go
+++ b/cli/cmd/logout.go
@@ -46,13 +46,13 @@ var logoutCmd = &cobra.Command{
 	Short: "Logs the current user out",
 	Long:  `Logs the current user out. Further actions on the controller are not permitted after this.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Logout attempt for user: ", nbUserName)
 
 		resp, err := api.Logout(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), nbUserName)
 		if err != nil {
 			spinner.Fail("Logout failed: ", err)
-			return err
+			return
 		}
 
 		userToken = ""
@@ -61,12 +61,10 @@ var logoutCmd = &cobra.Command{
 		err = viper.WriteConfig()
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		spinner.Success("User ", nbUserName, " successfully logged out at ", time.Unix((resp.Timestamp/1000000000), 0), ".")
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/networkElementCreate.go b/cli/cmd/networkElementCreate.go
index 4cc764922..e2ed6cb9d 100644
--- a/cli/cmd/networkElementCreate.go
+++ b/cli/cmd/networkElementCreate.go
@@ -47,12 +47,12 @@ var networkElementCreateCmd = &cobra.Command{
 Network element address must be provided with IP and port,e.g., 192.168.1.1:6030. User credentials need to be provided as parameters
 if they diverge from the default credentials (user:'admin' and pw:'arista').`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Creating new network element")
 		err := checkIPPort(address)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		opt := &tpb.TransportOption{
@@ -68,20 +68,18 @@ if they diverge from the default credentials (user:'admin' and pw:'arista').`,
 		pluginUUID, err := uuid.Parse(pluginID)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		resp, err := pndAdapter.AddNetworkElement(createContextWithAuthorization(), mneName, opt, pluginUUID)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		for _, r := range resp.GetResponses() {
 			spinner.Success("Network element has been created with ID: ", r.GetId())
 		}
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/networkElementList.go b/cli/cmd/networkElementList.go
index d61c2ea78..be6ce028a 100644
--- a/cli/cmd/networkElementList.go
+++ b/cli/cmd/networkElementList.go
@@ -44,13 +44,13 @@ var networkElementListCmd = &cobra.Command{
 	Short:   "list all network elements in current PND",
 	Long:    "List all orchestrated network network elements within the current PND.",
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Fetching data from controller")
 
 		resp, err := pndAdapter.GetFlattenedNetworkElements(createContextWithAuthorization())
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		data := pterm.TableData{[]string{"UUID", "Name", "Plugin-UUID"}}
@@ -62,10 +62,8 @@ var networkElementListCmd = &cobra.Command{
 
 		err = pterm.DefaultTable.WithHasHeader().WithData(data).Render()
 		if err != nil {
-			return err
+			return
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/networkElementPathDelete.go b/cli/cmd/networkElementPathDelete.go
index 51f1c9f34..b40bdccc1 100644
--- a/cli/cmd/networkElementPathDelete.go
+++ b/cli/cmd/networkElementPathDelete.go
@@ -48,18 +48,18 @@ var networkElementPathDeleteCmd = &cobra.Command{
 	Long: `Delete a path for a given orchestrated network network element.
 The network element UUID and request path must be specified as a positional arguments.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Create a path deletion request.")
 		mneid, err := uuid.Parse(args[0])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		path, err := ygot.StringToStructuredPath(args[1])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		resp, err := pndAdapter.ChangeMNE(
@@ -71,7 +71,7 @@ The network element UUID and request path must be specified as a positional argu
 		)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		for _, r := range resp.Responses {
@@ -81,7 +81,6 @@ The network element UUID and request path must be specified as a positional argu
 				spinner.Fail("An error occurred while creating a path deletion request for network element with ID: ", r.GetId(), r.GetStatus())
 			}
 		}
-		return nil
 	},
 }
 
diff --git a/cli/cmd/networkElementPathGet.go b/cli/cmd/networkElementPathGet.go
index d02fccf2e..f7ab234e4 100644
--- a/cli/cmd/networkElementPathGet.go
+++ b/cli/cmd/networkElementPathGet.go
@@ -47,11 +47,11 @@ var networkElementPathGetCmd = &cobra.Command{
 	Long: `Requests a path from a specified managed network element on the controller.
 The network element UUID and request path must be specified as a positional arguments.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		mneid, err := uuid.Parse(args[0])
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		res, err := pndAdapter.RequestPath(
@@ -61,7 +61,7 @@ The network element UUID and request path must be specified as a positional argu
 		)
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		for _, n := range res.MneNotification {
@@ -91,7 +91,6 @@ The network element UUID and request path must be specified as a positional argu
 
 			pterm.Info.Println(panels)
 		}
-		return nil
 	},
 }
 
diff --git a/cli/cmd/networkElementPathGetIntended.go b/cli/cmd/networkElementPathGetIntended.go
index 1e7e3c3a4..ceb8f50ed 100644
--- a/cli/cmd/networkElementPathGetIntended.go
+++ b/cli/cmd/networkElementPathGetIntended.go
@@ -49,11 +49,11 @@ var networkElementPathGetIntendedCmd = &cobra.Command{
 	Long: `Requests the intended path from a specified managed network element on the controller.
 The network element UUID and request path must be specified as a positional arguments.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		mneid, err := uuid.Parse(args[0])
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		res, err := pndAdapter.RequestIntendedPath(
@@ -63,7 +63,7 @@ The network element UUID and request path must be specified as a positional argu
 		)
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		var stringVal = "Update: "
@@ -100,8 +100,6 @@ The network element UUID and request path must be specified as a positional argu
 		if panel3 == "" {
 			fmt.Println(stringVal)
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/networkElementPathSet.go b/cli/cmd/networkElementPathSet.go
index 6dd9e1ddc..e29cbf332 100644
--- a/cli/cmd/networkElementPathSet.go
+++ b/cli/cmd/networkElementPathSet.go
@@ -32,7 +32,6 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	"fmt"
 	"os"
 
 	mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
@@ -58,17 +57,17 @@ only one value supported for now.
 The network element UUID, request path and value must be specified as positional arguments.
 To enable replacing behaviour (destructive!), set the --replace flag."`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Create a path set request.")
 		//NOTE: this currently only works in prompt mode
 		if c == nil {
 			spinner.Fail("Currently the SET command is only supported with 'gosdnc prompt'")
-			return fmt.Errorf("Currently the SET command is only supported with 'gosdnc prompt'")
+			return
 		}
 		mneid, err := uuid.Parse(args[0])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 		var value string
 		var operation mnepb.ApiOperation
@@ -83,7 +82,7 @@ To enable replacing behaviour (destructive!), set the --replace flag."`,
 		completer, ok := c.YangSchemaCompleterMap[mneid]
 		if !ok {
 			spinner.Fail("No schema completer found for network element ", mneid.String())
-			return fmt.Errorf("No schema completer found for network element %s", mneid.String())
+			return
 		}
 
 		var typedValue *gnmi.TypedValue
@@ -93,11 +92,11 @@ To enable replacing behaviour (destructive!), set the --replace flag."`,
 				typedValue, err = convertStringToGnmiTypedValue(args[2], completer.Entry.Type)
 				if err != nil {
 					spinner.Fail(err)
-					return err
+					return
 				}
 			} else {
 				spinner.Fail("The provided path is no leaf. Please provide a file with JSON-encoded text per RFC7951. Use '--file path' for this.")
-				return fmt.Errorf("The provided path is no leaf. Please provide a file with JSON-encoded text per RFC7951. Use '--file path' for this.")
+				return
 			}
 
 		} else {
@@ -105,7 +104,7 @@ To enable replacing behaviour (destructive!), set the --replace flag."`,
 			value, err = fileContentToString(file)
 			if err != nil {
 				spinner.Fail(err)
-				return err
+				return
 			}
 			typedValue = &gnmi.TypedValue{
 				Value: &gnmi.TypedValue_JsonIetfVal{
@@ -117,7 +116,7 @@ To enable replacing behaviour (destructive!), set the --replace flag."`,
 		path, err := ygot.StringToStructuredPath(args[1])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		resp, err := pndAdapter.ChangeMNE(
@@ -130,7 +129,7 @@ To enable replacing behaviour (destructive!), set the --replace flag."`,
 
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		for _, r := range resp.GetResponses() {
@@ -140,7 +139,6 @@ To enable replacing behaviour (destructive!), set the --replace flag."`,
 				executeFunc("change confirm " + r.GetId())
 			}
 		}
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/networkElementRemove.go b/cli/cmd/networkElementRemove.go
index f278b6460..b31fa1445 100644
--- a/cli/cmd/networkElementRemove.go
+++ b/cli/cmd/networkElementRemove.go
@@ -47,20 +47,19 @@ var networkElementRemoveCmd = &cobra.Command{
 	Long: `Deletes an orchestrated network network element on the controller.
 The network element UUID must be specified as a positional argument.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Removing network element with ID: ", args[0])
 		mneid, err := uuid.Parse(args[0])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 		_, err = pndAdapter.RemoveNetworkElement(createContextWithAuthorization(), mneid)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 		spinner.Success("Network element has been deleted, ID: ", mneid.String())
-		return nil
 	},
 }
 
diff --git a/cli/cmd/networkElementShow.go b/cli/cmd/networkElementShow.go
index 71581aec8..6e150c4da 100644
--- a/cli/cmd/networkElementShow.go
+++ b/cli/cmd/networkElementShow.go
@@ -46,11 +46,11 @@ Network element UUID or name must be specified as a positional argument.
 The network element information returned is the information as currently stored in the controller.
 The actual network element is not queried directly.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		resp, err := pndAdapter.GetNetworkElement(createContextWithAuthorization(), args[0])
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		mne := resp.GetMne()
@@ -64,8 +64,6 @@ The actual network element is not queried directly.`,
 		}).Srender()
 
 		pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels)
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/networkElementSubscribe.go b/cli/cmd/networkElementSubscribe.go
index 245d9f6fb..5b9682818 100644
--- a/cli/cmd/networkElementSubscribe.go
+++ b/cli/cmd/networkElementSubscribe.go
@@ -50,11 +50,11 @@ var deviceSubscribeCmd = &cobra.Command{
 	Long: `Requests a subscription on paths from a specified orchestrated network device on the controller.
 The device UUID and requested paths must be specified as a positional arguments.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		did, err := uuid.Parse(args[0])
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		subClient, err := pndAdapter.SubscribeMNEPath(
@@ -73,7 +73,7 @@ The device UUID and requested paths must be specified as a positional arguments.
 		)
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		for i := 0; i < 5; i++ {
@@ -95,8 +95,6 @@ The device UUID and requested paths must be specified as a positional arguments.
 
 			pterm.Println(subscribeResponse.String())
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/pluginList.go b/cli/cmd/pluginList.go
index 2a87fc246..8594f2836 100644
--- a/cli/cmd/pluginList.go
+++ b/cli/cmd/pluginList.go
@@ -44,12 +44,12 @@ var pluginListCmd = &cobra.Command{
 	Short:   "List all information about available plugins.",
 	Long:    `List all information about abailable plugins.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Fetching list of available plugins from the controller.")
 		resp, err := pndAdapter.GetAvailablePlugins(createContextWithAuthorization())
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		data := pterm.TableData{[]string{"UUID", "Name", "Author", "Firmware", "Version"}}
@@ -62,10 +62,8 @@ var pluginListCmd = &cobra.Command{
 
 		err = pterm.DefaultTable.WithHasHeader().WithData(data).Render()
 		if err != nil {
-			return err
+			return
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/pndCreate.go b/cli/cmd/pndCreate.go
index 5c3c83d53..dc4c6c6c6 100644
--- a/cli/cmd/pndCreate.go
+++ b/cli/cmd/pndCreate.go
@@ -49,12 +49,12 @@ campus building or site.
 
 A description must be passed as positional argument.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Creating new PND")
 		resp, err := api.AddPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), pndName, pndDescription)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		if resp.Status == ppb.Status_STATUS_OK {
@@ -62,8 +62,6 @@ A description must be passed as positional argument.`,
 		} else {
 			spinner.Fail("Failed creating the PND with name: ", pndName)
 		}
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/pndGet.go b/cli/cmd/pndGet.go
index 1c2c0a4d6..7fdabe07f 100644
--- a/cli/cmd/pndGet.go
+++ b/cli/cmd/pndGet.go
@@ -44,12 +44,12 @@ var pndGetCmd = &cobra.Command{
 	Short: "Request a PND by uuid.",
 	Long:  `Request a PND specified by uuid. The PND's UUID, Name and Description are returned.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Fetching requested PNDs from controller.")
 		resp, err := api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), args[0])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		pnd := resp.Pnd
@@ -65,7 +65,6 @@ var pndGetCmd = &cobra.Command{
 
 		spinner.Success()
 		pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels)
-		return nil
 	},
 }
 
diff --git a/cli/cmd/pndList.go b/cli/cmd/pndList.go
index 8e77bbb30..f6b15d422 100644
--- a/cli/cmd/pndList.go
+++ b/cli/cmd/pndList.go
@@ -45,12 +45,12 @@ var pndListCmd = &cobra.Command{
 	Short:   "List all information about the current PND",
 	Long:    `List all information about the current PND.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Fetching PND list from controller")
 		resp, err := api.GetPnds(createContextWithAuthorization(), pndAdapter.Endpoint())
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 
 		data := pterm.TableData{[]string{"UUID", "Name", "Description"}}
@@ -62,10 +62,8 @@ var pndListCmd = &cobra.Command{
 
 		err = pterm.DefaultTable.WithHasHeader().WithData(data).Render()
 		if err != nil {
-			return err
+			return
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/pndRemove.go b/cli/cmd/pndRemove.go
index 9b4eafca3..3c641a817 100644
--- a/cli/cmd/pndRemove.go
+++ b/cli/cmd/pndRemove.go
@@ -45,20 +45,19 @@ var pndRemoveCmd = &cobra.Command{
 	Short:   "Removes the PND with the provided ID",
 	Long:    "Removes the PND with the provided ID",
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		spinner, _ := pterm.DefaultSpinner.Start("Removing PND with ID: ", args[0])
 		pid, err := uuid.Parse(args[0])
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 		_, err = pndAdapter.RemovePnd(createContextWithAuthorization(), pid)
 		if err != nil {
 			spinner.Fail(err)
-			return err
+			return
 		}
 		spinner.Success("PND has been deleted, ID: ", pid.String())
-		return nil
 	},
 }
 
diff --git a/cli/cmd/pndUse.go b/cli/cmd/pndUse.go
index 5e849e2b3..b1c0cee7c 100644
--- a/cli/cmd/pndUse.go
+++ b/cli/cmd/pndUse.go
@@ -46,19 +46,19 @@ var pndUseCmd = &cobra.Command{
 	Short: "change currently used PND for the CLI",
 	Long:  `Change currently used PND for the CLI.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		var newPND = args[0]
 
 		newPndAdapter, err := adapter.NewPndAdapter(newPND, viper.GetString("controllerAPIEndpoint"))
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		_, err = api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), newPND)
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 
 		viper.Set("CLI_PND", newPND)
@@ -66,11 +66,10 @@ var pndUseCmd = &cobra.Command{
 		err = viper.WriteConfig()
 		if err != nil {
 			pterm.Error.Println(err)
-			return err
+			return
 		}
 		pndAdapter = newPndAdapter
 		pterm.Info.Printf("PND with ID: %s has been set for usage.\n", pndAdapter.ID().String())
-		return nil
 	},
 }
 
diff --git a/cli/cmd/prompt.go b/cli/cmd/prompt.go
index af3559c09..f297fe392 100644
--- a/cli/cmd/prompt.go
+++ b/cli/cmd/prompt.go
@@ -51,10 +51,17 @@ import (
 
 var c *PromptCompleter
 
+// suggestionTracker is used to keep track of the last used command in
+// combination with the resulting suggestions.
+type suggestionTracker struct {
+	lastCommand    *cobra.Command
+	lastSuggestion []prompt.Suggest
+}
+
 // PromptCompleter provides completion for a Network Element.
 type PromptCompleter struct {
 	YangSchemaCompleterMap map[uuid.UUID]*completer.YangSchemaCompleter
-	currentSuggestions     []prompt.Suggest
+	lastSuggestions        *suggestionTracker
 	// nolint:unused
 	document *prompt.Document
 	history  []string
@@ -137,14 +144,14 @@ func filterFlagSlice(input []string) (commandSlice []string, flagSlice []string)
 	return commandSlice, flagSlice
 }
 
-func networkElementPathCompletion(c *PromptCompleter, d prompt.Document, inputSplit []string) []prompt.Suggest {
+func networkElementPathCompletion(c *PromptCompleter, command *cobra.Command, d prompt.Document, inputSplit []string) []prompt.Suggest {
 	switch inputLen := len(inputSplit); inputLen {
 	case 3:
-		return c.updateSuggestionsThroughFunc(d, getNetworkElements)
+		return c.updateSuggestionsThroughFunc(d, command, getNetworkElements)
 	case 4:
 		id, err := uuid.Parse(inputSplit[inputLen-1])
 		if err != nil {
-			return c.updateSuggestionsThroughFunc(d, getNetworkElements)
+			return c.updateSuggestionsThroughFunc(d, command, getNetworkElements)
 		}
 		if c, ok := c.YangSchemaCompleterMap[id]; ok {
 			return c.Complete(d)
@@ -161,7 +168,7 @@ func networkElementPathCompletion(c *PromptCompleter, d prompt.Document, inputSp
 		if d.GetWordBeforeCursor() == "" || d.GetWordAfterCursor() != "" {
 			id, err := uuid.Parse(inputSplit[inputLen-2])
 			if err != nil {
-				return c.updateSuggestionsThroughFunc(d, getNetworkElements)
+				return c.updateSuggestionsThroughFunc(d, command, getNetworkElements)
 			}
 			if yc, ok := c.YangSchemaCompleterMap[id]; ok {
 				err := yc.UpdateEntry(inputSplit[inputLen-1])
@@ -173,7 +180,7 @@ func networkElementPathCompletion(c *PromptCompleter, d prompt.Document, inputSp
 		}
 		id, err := uuid.Parse(inputSplit[inputLen-2])
 		if err != nil {
-			return c.updateSuggestionsThroughFunc(d, getNetworkElements)
+			return c.updateSuggestionsThroughFunc(d, command, getNetworkElements)
 		}
 		if yc, ok := c.YangSchemaCompleterMap[id]; ok {
 			return yc.Complete(d)
@@ -184,15 +191,19 @@ func networkElementPathCompletion(c *PromptCompleter, d prompt.Document, inputSp
 	return []prompt.Suggest{}
 }
 
-func (pc *PromptCompleter) updateSuggestionsThroughFunc(d prompt.Document, fn func() ([]prompt.Suggest, error)) []prompt.Suggest {
-	if pc.currentSuggestions == nil {
+func (pc *PromptCompleter) updateSuggestionsThroughFunc(d prompt.Document, c *cobra.Command, fn func() ([]prompt.Suggest, error)) []prompt.Suggest {
+	if pc.lastSuggestions == nil {
 		var err error
-		pc.currentSuggestions, err = fn()
+		newSuggestions, err := fn()
+		pc.lastSuggestions = &suggestionTracker{
+			lastCommand:    c,
+			lastSuggestion: newSuggestions,
+		}
 		if err != nil {
-			return prompt.FilterHasPrefix(pc.currentSuggestions, d.GetWordBeforeCursor(), true)
+			return prompt.FilterHasPrefix(pc.lastSuggestions.lastSuggestion, d.GetWordBeforeCursor(), true)
 		}
 	}
-	return prompt.FilterHasPrefix(pc.currentSuggestions, d.GetWordBeforeCursor(), true)
+	return prompt.FilterHasPrefix(pc.lastSuggestions.lastSuggestion, d.GetWordBeforeCursor(), true)
 }
 
 func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, inputFlags []string, loaded []prompt.Suggest) []prompt.Suggest {
@@ -218,27 +229,53 @@ func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []s
 	switch cmd {
 	case pndUseCmd, pndGetCmd, pndRemoveCmd:
 		if len(inputSplitFiltered) < 3 || (len(inputSplitFiltered) == 3 && d.GetWordBeforeCursor() != "") {
-			suggestions := c.updateSuggestionsThroughFunc(d, getPnds)
+			if c.lastSuggestions != nil {
+				lastCommand := c.lastSuggestions.lastCommand
+				if lastCommand != pndUseCmd && lastCommand != pndGetCmd && lastCommand != pndRemoveCmd {
+					c.lastSuggestions = nil
+				}
+			}
+			suggestions := c.updateSuggestionsThroughFunc(d, cmd, getPnds)
 			return cobraCommandCompletion(cmd, d, inputFlags, suggestions)
 		}
 	case commitCmd:
+		if c.lastSuggestions != nil {
+			if c.lastSuggestions.lastCommand != commitCmd {
+				c.lastSuggestions = nil
+			}
+		}
 		if len(inputSplitFiltered) < 3 || (len(inputSplitFiltered) == 3 && d.GetWordBeforeCursor() != "") {
-			return c.updateSuggestionsThroughFunc(d, getPendingChanges)
+			return c.updateSuggestionsThroughFunc(d, cmd, getPendingChanges)
 		}
 	case confirmCmd:
+		if c.lastSuggestions != nil {
+			if c.lastSuggestions.lastCommand != confirmCmd {
+				c.lastSuggestions = nil
+			}
+		}
 		if len(inputSplitFiltered) < 3 || (len(inputSplitFiltered) == 3 && d.GetWordBeforeCursor() != "") {
-			return c.updateSuggestionsThroughFunc(d, getCommittedChanges)
+			return c.updateSuggestionsThroughFunc(d, cmd, getCommittedChanges)
 		}
 	case networkElementRemoveCmd:
+		if c.lastSuggestions != nil {
+			if c.lastSuggestions.lastCommand != networkElementRemoveCmd {
+				c.lastSuggestions = nil
+			}
+		}
 		if len(inputSplitFiltered) < 3 || (len(inputSplitFiltered) == 3 && d.GetWordBeforeCursor() != "") {
-			return c.updateSuggestionsThroughFunc(d, getNetworkElements)
+			return c.updateSuggestionsThroughFunc(d, cmd, getNetworkElements)
 		}
 	case networkElementCreateCmd:
+		if c.lastSuggestions != nil {
+			if c.lastSuggestions.lastCommand != networkElementCreateCmd {
+				c.lastSuggestions = nil
+			}
+		}
 		if len(inputFlags) != 0 {
 			if inputFlags[len(inputFlags)-1] == "--plugin-id" &&
 				((inputSplit[len(inputSplit)-1] == "--plugin-id" && d.GetWordBeforeCursor() == "") ||
 					(inputSplit[len(inputSplit)-2] == "--plugin-id" && d.GetWordBeforeCursor() != "")) {
-				return c.updateSuggestionsThroughFunc(d, getAvailablePlugins)
+				return c.updateSuggestionsThroughFunc(d, cmd, getAvailablePlugins)
 			} else {
 				return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{})
 			}
@@ -246,7 +283,13 @@ func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []s
 			return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{})
 		}
 	case networkElementPathGetCmd, networkElementPathGetIntendedCmd, networkElementPathSetCmd:
-		return networkElementPathCompletion(c, d, inputSplitFiltered)
+		if c.lastSuggestions != nil {
+			lastCommand := c.lastSuggestions.lastCommand
+			if lastCommand != networkElementPathGetCmd && lastCommand != networkElementPathGetIntendedCmd && lastCommand != networkElementPathSetCmd {
+				c.lastSuggestions = nil
+			}
+		}
+		return networkElementPathCompletion(c, cmd, d, inputSplitFiltered)
 	case networkElementShowCmd:
 		networkElements, err := getNetworkElements()
 		if err != nil {
@@ -254,7 +297,7 @@ func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []s
 		}
 		return networkElements
 	case networkElementCmd, pndCmd, changeCmd:
-		c.currentSuggestions = nil
+		c.lastSuggestions = nil
 		return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{})
 	default:
 		return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{})
@@ -387,7 +430,7 @@ var exitCmd = &cobra.Command{
 	Short: "The exit command exits the interactive prompt mode.",
 	Long:  `The exit command exits the interactive prompt mode.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		rawModeOff := exec.Command("/bin/stty", "-raw", "echo")
 		rawModeOff.Stdin = os.Stdin
 
@@ -396,9 +439,7 @@ var exitCmd = &cobra.Command{
 			logrus.Error(err)
 			os.Exit(1)
 		}
-
 		os.Exit(0)
-		return nil
 	},
 }
 
@@ -408,11 +449,9 @@ var promptCmd = &cobra.Command{
 	Long: `The prompt command rund the CLI in an interactive shell and
     provides the user with autocompletion and more...`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		c = NewPromptCompleter()
 		c.Run()
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/userCreate.go b/cli/cmd/userCreate.go
index f233acaf8..8a07b75ce 100644
--- a/cli/cmd/userCreate.go
+++ b/cli/cmd/userCreate.go
@@ -34,6 +34,7 @@ package cmd
 import (
 	apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
+	"github.com/pterm/pterm"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -47,7 +48,7 @@ var userCreateCmd = &cobra.Command{
     User name and password hashed with (add hash method here!) required,
     role is optional but needed to operate on PNDs.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 
 		roles := map[string]string{}
 		// only active pnd for now, add option for additional param later
@@ -64,11 +65,10 @@ var userCreateCmd = &cobra.Command{
 
 		resp, err := api.CreateUsers(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), users)
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 		log.Infof("Users created: %v", resp.Status)
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/userDelete.go b/cli/cmd/userDelete.go
index 160ed5f49..aa9fdc610 100644
--- a/cli/cmd/userDelete.go
+++ b/cli/cmd/userDelete.go
@@ -33,6 +33,7 @@ package cmd
 
 import (
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
+	"github.com/pterm/pterm"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -45,18 +46,17 @@ var userDeleteCmd = &cobra.Command{
 	Long: `Deletes a user with provided data.
     Requires the user name of the user which should be deleted.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 
 		// only one user for now, add more later if needed
 		users := []string{nbUserName}
 
 		resp, err := api.DeleteUsers(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), users)
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 		log.Infof("Users deleted: %v", resp.Status)
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/userGet.go b/cli/cmd/userGet.go
index f235141dc..357966913 100644
--- a/cli/cmd/userGet.go
+++ b/cli/cmd/userGet.go
@@ -34,6 +34,7 @@ package cmd
 import (
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
 	"github.com/google/uuid"
+	"github.com/pterm/pterm"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -45,7 +46,7 @@ var userGetCmd = &cobra.Command{
 	Short: "Requests one user",
 	Long:  `Requests one user using the provided name to search for it in the stored users.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		resp, err := api.GetUser(
 			createContextWithAuthorization(),
 			viper.GetString("controllerAPIEndpoint"),
@@ -53,15 +54,14 @@ var userGetCmd = &cobra.Command{
 			uuid.Nil,
 		)
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 
 		log.Infof("ID: %v, Name: %v \n", resp.User.Id, resp.User.Name)
 		for key, elem := range resp.User.Roles {
 			log.Infof("Role on PND: %v %v \n", key, elem)
 		}
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/cli/cmd/userGetAll.go b/cli/cmd/userGetAll.go
index cc9fa0973..8a5c650f0 100644
--- a/cli/cmd/userGetAll.go
+++ b/cli/cmd/userGetAll.go
@@ -33,6 +33,7 @@ package cmd
 
 import (
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
+	"github.com/pterm/pterm"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -44,10 +45,11 @@ var userGetAllCmd = &cobra.Command{
 	Short: "Requests all the available users",
 	Long:  `Requests all the available users.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		resp, err := api.GetAllUsers(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"))
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 
 		for i, u := range resp.User {
@@ -56,8 +58,6 @@ var userGetAllCmd = &cobra.Command{
 				log.Infof("Role on PND: %v %v \n", key, elem)
 			}
 		}
-
-		return nil
 	},
 }
 
diff --git a/cli/cmd/userUpdate.go b/cli/cmd/userUpdate.go
index 23c62b321..7849d5835 100644
--- a/cli/cmd/userUpdate.go
+++ b/cli/cmd/userUpdate.go
@@ -35,6 +35,7 @@ import (
 	apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
 	"code.fbi.h-da.de/danet/gosdn/controller/api"
 	"github.com/google/uuid"
+	"github.com/pterm/pterm"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -48,7 +49,7 @@ var userUpdateCmd = &cobra.Command{
     User name and password hashed with (add hash method here!) required,
     role is optional but needed to operate on PNDs.`,
 
-	RunE: func(cmd *cobra.Command, args []string) error {
+	Run: func(cmd *cobra.Command, args []string) {
 		existingUser, err := api.GetUser(
 			createContextWithAuthorization(),
 			viper.GetString("controllerAPIEndpoint"),
@@ -56,7 +57,8 @@ var userUpdateCmd = &cobra.Command{
 			uuid.Nil,
 		)
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 
 		roles := map[string]string{}
@@ -76,11 +78,10 @@ var userUpdateCmd = &cobra.Command{
 
 		resp, err := api.UpdateUsers(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), users)
 		if err != nil {
-			return err
+			pterm.Error.Println(err)
+			return
 		}
 		log.Infof("Users updated: %v", resp.Status)
-
-		return nil
 	},
 	PostRun: func(cmd *cobra.Command, args []string) {
 		// Necessary for prompt mode. The flag variables have to be resetted,
diff --git a/go.sum b/go.sum
index 30bfd8d30..c68dd12cd 100644
--- a/go.sum
+++ b/go.sum
@@ -547,8 +547,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0 h1:Rme6CE1aUTyV9WmrEPyGf1V+7W3iQzZ1DZkKnT6z9B0=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0/go.mod h1:Hbb13e3/WtqQ8U5hLGkek9gJvBLasHuPFI0UEGfnQ10=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1 h1:LSsiG61v9IzzxMkqEr6nrix4miJI62xlRjwT7BYD2SM=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1/go.mod h1:Hbb13e3/WtqQ8U5hLGkek9gJvBLasHuPFI0UEGfnQ10=
 github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
@@ -882,8 +880,6 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
 github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
 github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
 github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
-github.com/pterm/pterm v0.12.66 h1:bjsoMyUstaarzJ1NG7+1HGT7afR0JVMYsR3ooPeh4bo=
-github.com/pterm/pterm v0.12.66/go.mod h1:nFuT9ZVkkCi8o4L1dtWuYPwDQxggLh4C263qG5nTLpQ=
 github.com/pterm/pterm v0.12.67 h1:5iB7ajIQROYfxYD7+sFJ4+KJhFJ+xn7QOVBm4s6RUF0=
 github.com/pterm/pterm v0.12.67/go.mod h1:nFuT9ZVkkCi8o4L1dtWuYPwDQxggLh4C263qG5nTLpQ=
 github.com/rabbitmq/amqp091-go v1.8.1 h1:RejT1SBUim5doqcL6s7iN6SBmsQqyTgXb1xMlH0h1hA=
-- 
GitLab