From d4ab3802f0daad75c465ccdcc87e8ebacdb719d4 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Wed, 9 Oct 2024 12:08:15 -0400 Subject: [PATCH] added pluginoutput and pluginstatus fetch --- blockchain/bl_plugins.go | 147 +++++++++++++++++++++++++++++++++++++-- blockchain/blockchain.go | 8 ++- blockchain/interface.go | 27 +++++++ mobile/blockchain.go | 12 ++++ 4 files changed, 189 insertions(+), 5 deletions(-) diff --git a/blockchain/bl_plugins.go b/blockchain/bl_plugins.go index 7bb319c..d401581 100644 --- a/blockchain/bl_plugins.go +++ b/blockchain/bl_plugins.go @@ -466,6 +466,139 @@ func (bl *FxBlockchain) showPluginStatusImpl(ctx context.Context, pluginName str return formattedLines, nil } +func (bl *FxBlockchain) GetInstallOutput(ctx context.Context, to peer.ID, pluginName string, paramsString string) ([]byte, error) { + if bl.allowTransientConnection { + ctx = network.WithUseTransient(ctx, "fx.blockchain") + } + + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(map[string]string{"plugin_name": pluginName, "params": paramsString}); err != nil { + return nil, err + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://"+to.String()+".invalid/"+actionGetInstallOutput, &buf) + if err != nil { + return nil, err + } + resp, err := bl.c.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return io.ReadAll(resp.Body) +} + +func (bl *FxBlockchain) GetInstallStatus(ctx context.Context, to peer.ID, pluginName string) ([]byte, error) { + if bl.allowTransientConnection { + ctx = network.WithUseTransient(ctx, "fx.blockchain") + } + + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(map[string]string{"plugin_name": pluginName}); err != nil { + return nil, err + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://"+to.String()+".invalid/"+actionGetInstallStatus, &buf) + if err != nil { + return nil, err + } + resp, err := bl.c.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return io.ReadAll(resp.Body) +} + +func (bl *FxBlockchain) getInstallOutputImpl(ctx context.Context, pluginName string, paramsString string) ([]byte, error) { + output := make(map[string]string) + params := strings.Split(paramsString, ",,,,") + + for _, param := range params { + parts := strings.Split(param, "====") + if len(parts) != 2 { + continue + } + name := parts[0] + filePath := fmt.Sprintf("/internal/%s/%s.txt", pluginName, name) + content, err := os.ReadFile(filePath) + if err != nil { + if os.IsNotExist(err) { + output[name] = "" + } else { + return json.Marshal(map[string]interface{}{ + "msg": fmt.Errorf("error reading file for %s: %w", name, err), + "status": false, + }) + } + } else { + output[name] = strings.TrimSpace(string(content)) + } + } + + return json.Marshal(map[string]interface{}{ + "msg": output, + "status": true, + }) +} + +func (bl *FxBlockchain) getInstallStatusImpl(ctx context.Context, pluginName string) ([]byte, error) { + filePath := fmt.Sprintf("/internal/%s/status.txt", pluginName) + content, err := os.ReadFile(filePath) + if err != nil { + if os.IsNotExist(err) { + return json.Marshal(map[string]interface{}{ + "status": true, + "msg": "Status file not found", + }) + } + return json.Marshal(map[string]interface{}{ + "status": false, + "msg": fmt.Errorf("error reading status file for %s: %w", pluginName, err), + }) + } + + return json.Marshal(map[string]interface{}{ + "status": true, + "msg": strings.TrimSpace(string(content)), + }) +} + +func (bl *FxBlockchain) HandleGetInstallOutput(w http.ResponseWriter, r *http.Request) { + var req struct { + PluginName string `json:"plugin_name"` + Params string `json:"params"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + result, err := bl.getInstallOutputImpl(r.Context(), req.PluginName, req.Params) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Write(result) +} + +func (bl *FxBlockchain) HandleGetInstallStatus(w http.ResponseWriter, r *http.Request) { + var req struct { + PluginName string `json:"plugin_name"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + result, err := bl.getInstallStatusImpl(r.Context(), req.PluginName) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Write(result) +} + func (bl *FxBlockchain) handlePluginAction(ctx context.Context, from peer.ID, w http.ResponseWriter, r *http.Request, action string) { log := log.With("action", action, "from", from) log.Debug("started handlePluginAction") @@ -497,19 +630,25 @@ func (bl *FxBlockchain) handlePluginAction(ctx context.Context, from peer.ID, w switch action { case actionListPlugins: - log.Debug("handlePluginAction: calling method") + log.Debug("handlePluginAction: calling method actionListPlugins") result, err = bl.listPluginsImpl(ctx) case actionListActivePlugins: - log.Debug("handlePluginAction: calling method") + log.Debug("handlePluginAction: calling method actionListActivePlugins") result, err = bl.listActivePluginsImpl(ctx) case actionInstallPlugin: - log.Debugw("handlePluginAction: calling method", "PluginName", req.PluginName, "params", req.Params) + log.Debugw("handlePluginAction: calling method actionInstallPlugin", "PluginName", req.PluginName, "params", req.Params) result, err = bl.installPluginImpl(ctx, req.PluginName, req.Params) case actionUninstallPlugin: - log.Debug("handlePluginAction: calling method") + log.Debug("handlePluginAction: calling method actionUninstallPlugin") result, err = bl.uninstallPluginImpl(ctx, req.PluginName) case actionShowPluginStatus: result, err = bl.ShowPluginStatus(ctx, req.PluginName, req.Lines) + case actionGetInstallOutput: + log.Debugw("handlePluginAction: calling method", "PluginName", req.PluginName, "params", req.Params) + result, err = bl.getInstallOutputImpl(ctx, req.PluginName, req.Params) + case actionGetInstallStatus: + log.Debugw("handlePluginAction: calling method actionGetInstallStatus", "PluginName", req.PluginName) + result, err = bl.getInstallStatusImpl(ctx, req.PluginName) default: log.Error("Invalid action") http.Error(w, "Invalid action", http.StatusBadRequest) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index 33c2c35..7bd59b4 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -559,6 +559,12 @@ func (bl *FxBlockchain) serve(w http.ResponseWriter, r *http.Request) { actionShowPluginStatus: func(from peer.ID, w http.ResponseWriter, r *http.Request) { bl.handlePluginAction(r.Context(), from, w, r, actionShowPluginStatus) }, + actionGetInstallOutput: func(from peer.ID, w http.ResponseWriter, r *http.Request) { + bl.handlePluginAction(r.Context(), from, w, r, actionGetInstallOutput) + }, + actionGetInstallStatus: func(from peer.ID, w http.ResponseWriter, r *http.Request) { + bl.handlePluginAction(r.Context(), from, w, r, actionGetInstallStatus) + }, } // Look up the function in the map and call it @@ -972,7 +978,7 @@ func (bl *FxBlockchain) authorized(pid peer.ID, action string) bool { switch action { case actionReplicateInPool: return (bl.authorizer == bl.h.ID() || bl.authorizer == "") - case actionBloxFreeSpace, actionAccountFund, actionManifestBatchUpload, actionAssetsBalance, actionGetDatastoreSize, actionGetFolderSize, actionFindBestAndTargetInLogs, actionFetchContainerLogs, actionEraseBlData, actionWifiRemoveall, actionReboot, actionPartition, actionDeleteWifi, actionDisconnectWifi, actionDeleteFulaConfig, actionGetAccount, actionSeeded, actionAccountExists, actionPoolCreate, actionPoolJoin, actionPoolCancelJoin, actionPoolRequests, actionPoolList, actionPoolVote, actionPoolLeave, actionManifestUpload, actionManifestStore, actionManifestAvailable, actionManifestRemove, actionManifestRemoveStorer, actionManifestRemoveStored, actionTransferToMumbai, actionListPlugins, actionListActivePlugins, actionInstallPlugin, actionUninstallPlugin: + case actionBloxFreeSpace, actionAccountFund, actionManifestBatchUpload, actionAssetsBalance, actionGetDatastoreSize, actionGetFolderSize, actionFindBestAndTargetInLogs, actionFetchContainerLogs, actionEraseBlData, actionWifiRemoveall, actionReboot, actionPartition, actionDeleteWifi, actionDisconnectWifi, actionDeleteFulaConfig, actionGetAccount, actionSeeded, actionAccountExists, actionPoolCreate, actionPoolJoin, actionPoolCancelJoin, actionPoolRequests, actionPoolList, actionPoolVote, actionPoolLeave, actionManifestUpload, actionManifestStore, actionManifestAvailable, actionManifestRemove, actionManifestRemoveStorer, actionManifestRemoveStored, actionTransferToMumbai, actionListPlugins, actionListActivePlugins, actionInstallPlugin, actionUninstallPlugin, actionGetInstallStatus, actionGetInstallOutput: bl.authorizedPeersLock.RLock() _, ok := bl.authorizedPeers[pid] bl.authorizedPeersLock.RUnlock() diff --git a/blockchain/interface.go b/blockchain/interface.go index 37d0443..2b17265 100644 --- a/blockchain/interface.go +++ b/blockchain/interface.go @@ -61,6 +61,8 @@ const ( actionUninstallPlugin = "uninstall-plugin" actionShowPluginStatus = "show-plugin-status" actionListActivePlugins = "list-active-plugins" + actionGetInstallOutput = "get-install-output" + actionGetInstallStatus = "get-install-status" ) type ReplicateRequest struct { @@ -439,6 +441,25 @@ type ListActivePluginsResponse struct { ActivePlugins []string `json:"active_plugins"` } +// GetInstallOutput +type GetInstallOutputRequest struct { + PluginName string `json:"plugin_name"` + Params string `json:"params"` +} + +type GetInstallOutputResponse struct { + Outputs map[string]string `json:"outputs"` +} + +// GetInstallStatus +type GetInstallStatusRequest struct { + PluginName string `json:"plugin_name"` +} + +type GetInstallStatusResponse struct { + Status string `json:"status"` +} + type Blockchain interface { Seeded(context.Context, peer.ID, SeededRequest) ([]byte, error) AccountExists(context.Context, peer.ID, AccountExistsRequest) ([]byte, error) @@ -487,6 +508,8 @@ type Blockchain interface { InstallPlugin(context.Context, peer.ID, string, string) ([]byte, error) UninstallPlugin(context.Context, peer.ID, string) ([]byte, error) ShowPluginStatus(context.Context, string, int) ([]byte, error) + GetInstallOutput(context.Context, peer.ID, string, string) ([]byte, error) + GetInstallStatus(context.Context, peer.ID, string) ([]byte, error) } var requestTypes = map[string]reflect.Type{ @@ -538,6 +561,8 @@ var requestTypes = map[string]reflect.Type{ actionInstallPlugin: reflect.TypeOf(InstallPluginRequest{}), actionUninstallPlugin: reflect.TypeOf(UninstallPluginRequest{}), actionShowPluginStatus: reflect.TypeOf(ShowPluginStatusRequest{}), + actionGetInstallOutput: reflect.TypeOf(GetInstallOutputRequest{}), + actionGetInstallStatus: reflect.TypeOf(GetInstallStatusRequest{}), } var responseTypes = map[string]reflect.Type{ @@ -589,4 +614,6 @@ var responseTypes = map[string]reflect.Type{ actionInstallPlugin: reflect.TypeOf(InstallPluginResponse{}), actionUninstallPlugin: reflect.TypeOf(UninstallPluginResponse{}), actionShowPluginStatus: reflect.TypeOf(ShowPluginStatusResponse{}), + actionGetInstallOutput: reflect.TypeOf(GetInstallOutputResponse{}), + actionGetInstallStatus: reflect.TypeOf(GetInstallStatusResponse{}), } diff --git a/mobile/blockchain.go b/mobile/blockchain.go index 83a7757..e5bce68 100644 --- a/mobile/blockchain.go +++ b/mobile/blockchain.go @@ -303,3 +303,15 @@ func (c *Client) ShowPluginStatus(pluginName string, lines int) ([]byte, error) ctx := context.TODO() return c.bl.ShowPluginStatus(ctx, pluginName, lines) } + +// InstallPlugin requests the blox to install a specific plugin +func (c *Client) GetInstallOutput(pluginName string, params string) ([]byte, error) { + ctx := context.TODO() + return c.bl.GetInstallOutput(ctx, c.bloxPid, pluginName, params) +} + +// InstallPlugin requests the blox to install a specific plugin +func (c *Client) GetInstallStatus(pluginName string) ([]byte, error) { + ctx := context.TODO() + return c.bl.GetInstallStatus(ctx, c.bloxPid, pluginName) +}