forked from mattermost/mattermost
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MM-57018: support reattaching plugins (mattermost#26421)
* ProfileImageBytes for EnsureBotOptions * leverage plugintest.NewAPI * fix linting * add UpdateUserRoles to plugin api * MM-57018: support reattaching plugins Expose a local-only API for reattaching plugins: instead of the server starting and managing the process itself, allow the plugin to be launched externally (eg within a unit test) and reattach to an existing server instance to provide the unit test with a fully functional RPC API, sidestepping the need for mocking the plugin API in most cases. In the future, this may become the basis for running plugins in a sidecar container. Fixes: https://mattermost.atlassian.net/browse/MM-57018 * drop unused supervisor.pid * factor out checkMinServerVersion * factor out startPluginServer * restore missing setPluginState on successful reattach * avoid passing around a stale registeredPlugin * inline initializePluginImplementation * have IsValid return an error * explicitly close rpcClient In the case of reattached plugins, the Unix socket won't necessarily disappear leaving the muxBrokers blocked indefinitely. And `Kill()` doesn't do anything if there's no process being managed. * explicitly detachPlugin * emphasize gRPC not being supported --------- Co-authored-by: Mattermost Build <[email protected]>
- Loading branch information
1 parent
f5ea554
commit 2230fb6
Showing
12 changed files
with
582 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||
// See LICENSE.txt for license information. | ||
package app | ||
|
||
import ( | ||
"net/http" | ||
|
||
"github.com/mattermost/mattermost/server/public/model" | ||
) | ||
|
||
// ReattachPlugin allows the server to bind to an existing plugin instance launched elsewhere. | ||
func (a *App) ReattachPlugin(manifest *model.Manifest, pluginReattachConfig *model.PluginReattachConfig) *model.AppError { | ||
return a.ch.ReattachPlugin(manifest, pluginReattachConfig) | ||
} | ||
|
||
// ReattachPlugin allows the server to bind to an existing plugin instance launched elsewhere. | ||
func (ch *Channels) ReattachPlugin(manifest *model.Manifest, pluginReattachConfig *model.PluginReattachConfig) *model.AppError { | ||
pluginsEnvironment := ch.GetPluginsEnvironment() | ||
if pluginsEnvironment == nil { | ||
return model.NewAppError("ReattachPlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented) | ||
} | ||
|
||
ch.DetachPlugin(manifest.Id) | ||
|
||
// Reattach to the plugin | ||
if err := pluginsEnvironment.Reattach(manifest, pluginReattachConfig); err != nil { | ||
return model.NewAppError("ReattachPlugin", "app.plugin.reattach.app_error", nil, "", http.StatusInternalServerError).Wrap(err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// DetachPlugin allows the server to bind to an existing plugin instance launched elsewhere. | ||
func (a *App) DetachPlugin(pluginId string) *model.AppError { | ||
return a.ch.DetachPlugin(pluginId) | ||
} | ||
|
||
// DetachPlugin allows the server to bind to an existing plugin instance launched elsewhere. | ||
func (ch *Channels) DetachPlugin(pluginID string) *model.AppError { | ||
pluginsEnvironment := ch.GetPluginsEnvironment() | ||
if pluginsEnvironment == nil { | ||
return model.NewAppError("DetachPlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented) | ||
} | ||
|
||
// Deactivate and remove any existing plugin, if present. | ||
pluginsEnvironment.Deactivate(pluginID) | ||
pluginsEnvironment.RemovePlugin(pluginID) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package model | ||
|
||
import ( | ||
"net" | ||
"net/http" | ||
|
||
"github.com/hashicorp/go-plugin" | ||
) | ||
|
||
// PluginReattachConfig is a serializable version of go-plugin's ReattachConfig. | ||
type PluginReattachConfig struct { | ||
Protocol string | ||
ProtocolVersion int | ||
Addr net.UnixAddr | ||
Pid int | ||
Test bool | ||
} | ||
|
||
func NewPluginReattachConfig(pluginReattachmentConfig *plugin.ReattachConfig) *PluginReattachConfig { | ||
return &PluginReattachConfig{ | ||
Protocol: string(pluginReattachmentConfig.Protocol), | ||
ProtocolVersion: pluginReattachmentConfig.ProtocolVersion, | ||
Addr: net.UnixAddr{ | ||
Name: pluginReattachmentConfig.Addr.String(), | ||
Net: pluginReattachmentConfig.Addr.Network(), | ||
}, | ||
Pid: pluginReattachmentConfig.Pid, | ||
Test: pluginReattachmentConfig.Test, | ||
} | ||
} | ||
|
||
func (prc *PluginReattachConfig) ToHashicorpPluginReattachmentConfig() *plugin.ReattachConfig { | ||
addr := prc.Addr | ||
|
||
return &plugin.ReattachConfig{ | ||
Protocol: plugin.Protocol(prc.Protocol), | ||
ProtocolVersion: prc.ProtocolVersion, | ||
Addr: &addr, | ||
Pid: prc.Pid, | ||
ReattachFunc: nil, | ||
Test: prc.Test, | ||
} | ||
} | ||
|
||
type PluginReattachRequest struct { | ||
Manifest *Manifest | ||
PluginReattachConfig *PluginReattachConfig | ||
} | ||
|
||
func (prr *PluginReattachRequest) IsValid() *AppError { | ||
if prr.Manifest == nil { | ||
return NewAppError("PluginReattachRequest.IsValid", "plugin_reattach_request.is_valid.manifest.app_error", nil, "", http.StatusBadRequest) | ||
} | ||
if prr.PluginReattachConfig == nil { | ||
return NewAppError("PluginReattachRequest.IsValid", "plugin_reattach_request.is_valid.plugin_reattach_config.app_error", nil, "", http.StatusBadRequest) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.