2019-11-29 06:59:40 -05:00
|
|
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
|
|
|
// See LICENSE.txt for license information.
|
2017-11-27 17:23:35 -05:00
|
|
|
|
|
|
|
|
package app
|
|
|
|
|
|
|
|
|
|
import (
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
"archive/tar"
|
|
|
|
|
"compress/gzip"
|
2018-10-03 16:04:37 -04:00
|
|
|
"crypto/sha256"
|
|
|
|
|
"encoding/base64"
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
"encoding/json"
|
2019-07-18 14:05:53 -04:00
|
|
|
"fmt"
|
2022-08-09 07:25:46 -04:00
|
|
|
"io"
|
2019-07-18 14:05:53 -04:00
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
"sort"
|
2017-11-27 17:23:35 -05:00
|
|
|
"testing"
|
2019-12-03 04:46:15 -05:00
|
|
|
"time"
|
2017-11-27 17:23:35 -05:00
|
|
|
|
2019-11-04 07:49:54 -05:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
2023-06-11 01:24:35 -04:00
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
|
|
|
"github.com/mattermost/mattermost/server/public/plugin"
|
|
|
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
|
|
|
"github.com/mattermost/mattermost/server/v8/channels/testlib"
|
|
|
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
2017-11-27 17:23:35 -05:00
|
|
|
)
|
|
|
|
|
|
2018-10-03 16:04:37 -04:00
|
|
|
func getHashedKey(key string) string {
|
|
|
|
|
hash := sha256.New()
|
|
|
|
|
hash.Write([]byte(key))
|
|
|
|
|
return base64.StdEncoding.EncodeToString(hash.Sum(nil))
|
|
|
|
|
}
|
2018-11-27 15:50:31 -05:00
|
|
|
|
2017-11-27 17:23:35 -05:00
|
|
|
func TestPluginKeyValueStore(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2017-11-27 17:23:35 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
pluginID := "testpluginid"
|
2017-11-27 17:23:35 -05:00
|
|
|
|
2018-11-27 15:50:31 -05:00
|
|
|
defer func() {
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.DeletePluginKey(pluginID, "key"))
|
|
|
|
|
assert.Nil(t, th.App.DeletePluginKey(pluginID, "key2"))
|
|
|
|
|
assert.Nil(t, th.App.DeletePluginKey(pluginID, "key3"))
|
|
|
|
|
assert.Nil(t, th.App.DeletePluginKey(pluginID, "key4"))
|
2018-11-27 15:50:31 -05:00
|
|
|
}()
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.SetPluginKey(pluginID, "key", []byte("test")))
|
|
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "key")
|
2017-11-27 17:23:35 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test"), ret)
|
|
|
|
|
|
|
|
|
|
// Test inserting over existing entries
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.SetPluginKey(pluginID, "key", []byte("test2")))
|
|
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key")
|
2018-11-27 15:50:31 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test2"), ret)
|
2017-11-27 17:23:35 -05:00
|
|
|
|
|
|
|
|
// Test getting non-existent key
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "notakey")
|
2017-11-27 17:23:35 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Nil(t, ret)
|
|
|
|
|
|
2018-11-27 15:50:31 -05:00
|
|
|
// Test deleting non-existent keys.
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.DeletePluginKey(pluginID, "notrealkey"))
|
2018-10-03 16:04:37 -04:00
|
|
|
|
2018-11-27 15:50:31 -05:00
|
|
|
// Verify behaviour for the old approach that involved storing the hashed keys.
|
2018-10-03 16:04:37 -04:00
|
|
|
hashedKey2 := getHashedKey("key2")
|
2018-11-27 15:50:31 -05:00
|
|
|
kv := &model.PluginKeyValue{
|
2021-02-25 14:22:27 -05:00
|
|
|
PluginId: pluginID,
|
2018-11-27 15:50:31 -05:00
|
|
|
Key: hashedKey2,
|
|
|
|
|
Value: []byte("test"),
|
|
|
|
|
ExpireAt: 0,
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-06 04:04:21 -04:00
|
|
|
_, nErr := th.App.Srv().Store().Plugin().SaveOrUpdate(kv)
|
2021-02-16 06:00:01 -05:00
|
|
|
assert.NoError(t, nErr)
|
2018-11-27 15:50:31 -05:00
|
|
|
|
|
|
|
|
// Test fetch by keyname (this key does not exist but hashed key will be used for lookup)
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key2")
|
2018-11-27 15:50:31 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, kv.Value, ret)
|
|
|
|
|
|
|
|
|
|
// Test fetch by hashed keyname
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, hashedKey2)
|
2018-11-27 15:50:31 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, kv.Value, ret)
|
|
|
|
|
|
|
|
|
|
// Test ListKeys
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.SetPluginKey(pluginID, "key3", []byte("test3")))
|
|
|
|
|
assert.Nil(t, th.App.SetPluginKey(pluginID, "key4", []byte("test4")))
|
2018-11-29 13:02:06 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err := th.App.ListPluginKeys(pluginID, 0, 1)
|
2018-10-03 16:04:37 -04:00
|
|
|
assert.Nil(t, err)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Equal(t, []string{"key"}, list)
|
2018-10-03 16:04:37 -04:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 1, 1)
|
2018-10-03 16:04:37 -04:00
|
|
|
assert.Nil(t, err)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Equal(t, []string{"key3"}, list)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 0, 4)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 0, 2)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []string{"key", "key3"}, list)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 1, 2)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []string{"key4", hashedKey2}, list)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 2, 2)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []string{}, list)
|
2018-10-03 16:04:37 -04:00
|
|
|
|
2018-11-27 15:50:31 -05:00
|
|
|
// List Keys bad input
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 0, 0)
|
2018-10-03 16:04:37 -04:00
|
|
|
assert.Nil(t, err)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
|
2018-10-03 16:04:37 -04:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, 0, -1)
|
2018-10-03 16:04:37 -04:00
|
|
|
assert.Nil(t, err)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
|
2018-10-03 16:04:37 -04:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, -1, 1)
|
2018-10-03 16:04:37 -04:00
|
|
|
assert.Nil(t, err)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Equal(t, []string{"key"}, list)
|
2018-10-03 16:04:37 -04:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err = th.App.ListPluginKeys(pluginID, -1, 0)
|
2018-10-03 16:04:37 -04:00
|
|
|
assert.Nil(t, err)
|
2018-11-29 13:02:06 -05:00
|
|
|
assert.Equal(t, []string{"key", "key3", "key4", hashedKey2}, list)
|
2017-11-27 17:23:35 -05:00
|
|
|
}
|
2017-12-01 10:07:32 -05:00
|
|
|
|
2019-04-23 13:35:17 -04:00
|
|
|
func TestPluginKeyValueStoreCompareAndSet(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2019-04-23 13:35:17 -04:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
pluginID := "testpluginid"
|
2019-04-23 13:35:17 -04:00
|
|
|
|
|
|
|
|
defer func() {
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.DeletePluginKey(pluginID, "key"))
|
2019-04-23 13:35:17 -04:00
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Set using Set api for key2
|
2021-02-25 14:22:27 -05:00
|
|
|
assert.Nil(t, th.App.SetPluginKey(pluginID, "key2", []byte("test")))
|
|
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "key2")
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test"), ret)
|
|
|
|
|
|
|
|
|
|
// Attempt to insert value for key2
|
2021-02-25 14:22:27 -05:00
|
|
|
updated, err := th.App.CompareAndSetPluginKey(pluginID, "key2", nil, []byte("test2"))
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.False(t, updated)
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key2")
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test"), ret)
|
|
|
|
|
|
|
|
|
|
// Insert new value for key
|
2021-02-25 14:22:27 -05:00
|
|
|
updated, err = th.App.CompareAndSetPluginKey(pluginID, "key", nil, []byte("test"))
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.True(t, updated)
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key")
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test"), ret)
|
|
|
|
|
|
|
|
|
|
// Should fail to insert again
|
2021-02-25 14:22:27 -05:00
|
|
|
updated, err = th.App.CompareAndSetPluginKey(pluginID, "key", nil, []byte("test3"))
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.False(t, updated)
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key")
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test"), ret)
|
|
|
|
|
|
|
|
|
|
// Test updating using incorrect old value
|
2021-02-25 14:22:27 -05:00
|
|
|
updated, err = th.App.CompareAndSetPluginKey(pluginID, "key", []byte("oldvalue"), []byte("test3"))
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.False(t, updated)
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key")
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test"), ret)
|
|
|
|
|
|
|
|
|
|
// Test updating using correct old value
|
2021-02-25 14:22:27 -05:00
|
|
|
updated, err = th.App.CompareAndSetPluginKey(pluginID, "key", []byte("test"), []byte("test2"))
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.True(t, updated)
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key")
|
2019-04-23 13:35:17 -04:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("test2"), ret)
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 07:49:54 -05:00
|
|
|
func TestPluginKeyValueStoreSetWithOptionsJSON(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2021-02-25 14:22:27 -05:00
|
|
|
pluginID := "testpluginid"
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
t.Run("storing a value without providing options works", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "key", []byte("value-1"), model.PluginKVSetOptions{})
|
2019-11-04 07:49:54 -05:00
|
|
|
assert.True(t, result)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
|
|
// and I can get it back!
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "key")
|
2019-11-04 07:49:54 -05:00
|
|
|
assert.Nil(t, err)
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Equal(t, []byte(`value-1`), ret)
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("test that setting it atomic when it doesn't match doesn't change anything", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
err := th.App.SetPluginKey(pluginID, "key", []byte("value-1"))
|
2019-12-03 04:46:15 -05:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "key", []byte("value-3"), model.PluginKVSetOptions{
|
2019-12-03 04:46:15 -05:00
|
|
|
Atomic: true,
|
|
|
|
|
OldValue: []byte("value-2"),
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
assert.False(t, result)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
|
|
// test that the value didn't change
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "key")
|
2019-11-04 07:49:54 -05:00
|
|
|
assert.Nil(t, err)
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Equal(t, []byte(`value-1`), ret)
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("test the atomic change with the proper old value", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
err := th.App.SetPluginKey(pluginID, "key", []byte("value-2"))
|
2019-12-03 04:46:15 -05:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "key", []byte("value-3"), model.PluginKVSetOptions{
|
2019-12-03 04:46:15 -05:00
|
|
|
Atomic: true,
|
|
|
|
|
OldValue: []byte("value-2"),
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
assert.True(t, result)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
|
|
// test that the value did change
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "key")
|
2019-11-04 07:49:54 -05:00
|
|
|
assert.Nil(t, err)
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Equal(t, []byte(`value-3`), ret)
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
t.Run("when new value is nil and old value matches with the current, it should delete the currently set value", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
// first set a value.
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "nil-test-key-2", []byte("value-1"), model.PluginKVSetOptions{})
|
2019-12-03 04:46:15 -05:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
require.True(t, result)
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
// now it should delete the set value.
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err = th.App.SetPluginKeyWithOptions(pluginID, "nil-test-key-2", nil, model.PluginKVSetOptions{
|
2019-12-03 04:46:15 -05:00
|
|
|
Atomic: true,
|
|
|
|
|
OldValue: []byte("value-1"),
|
|
|
|
|
})
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.True(t, result)
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "nil-test-key-2")
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Nil(t, ret)
|
|
|
|
|
})
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
t.Run("when new value is nil and there is a value set for the key already, it should delete the currently set value", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
// first set a value.
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "nil-test-key-3", []byte("value-1"), model.PluginKVSetOptions{})
|
2019-12-03 04:46:15 -05:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
require.True(t, result)
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
// now it should delete the set value.
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err = th.App.SetPluginKeyWithOptions(pluginID, "nil-test-key-3", nil, model.PluginKVSetOptions{})
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.True(t, result)
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2020-01-31 08:58:48 -05:00
|
|
|
// verify a nil value is returned
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "nil-test-key-3")
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Nil(t, ret)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
|
|
|
|
// verify the row is actually gone
|
2021-02-25 14:22:27 -05:00
|
|
|
list, err := th.App.ListPluginKeys(pluginID, 0, 1)
|
2020-01-31 08:58:48 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Empty(t, list)
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
t.Run("when old value is nil and there is no value set for the key before, it should set the new value", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "nil-test-key-4", []byte("value-1"), model.PluginKVSetOptions{
|
2019-12-03 04:46:15 -05:00
|
|
|
Atomic: true,
|
|
|
|
|
OldValue: nil,
|
|
|
|
|
})
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.True(t, result)
|
2019-11-04 07:49:54 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "nil-test-key-4")
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte("value-1"), ret)
|
2019-11-04 07:49:54 -05:00
|
|
|
})
|
|
|
|
|
|
2019-12-03 04:46:15 -05:00
|
|
|
t.Run("test that value is set and unset with ExpireInSeconds", func(t *testing.T) {
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2020-01-31 08:58:48 -05:00
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
result, err := th.App.SetPluginKeyWithOptions(pluginID, "key", []byte("value-1"), model.PluginKVSetOptions{
|
2019-12-03 04:46:15 -05:00
|
|
|
ExpireInSeconds: 1,
|
|
|
|
|
})
|
|
|
|
|
assert.True(t, result)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
|
|
// test that the value is set
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err := th.App.GetPluginKey(pluginID, "key")
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Equal(t, []byte(`value-1`), ret)
|
|
|
|
|
|
|
|
|
|
// test that the value is not longer
|
|
|
|
|
time.Sleep(1500 * time.Millisecond)
|
|
|
|
|
|
2021-02-25 14:22:27 -05:00
|
|
|
ret, err = th.App.GetPluginKey(pluginID, "key")
|
2019-12-03 04:46:15 -05:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assert.Nil(t, ret)
|
|
|
|
|
})
|
2019-11-04 07:49:54 -05:00
|
|
|
}
|
|
|
|
|
|
2018-05-23 14:26:35 -04:00
|
|
|
func TestGetPluginStatusesDisabled(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2018-05-23 14:26:35 -04:00
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = false
|
2018-03-13 10:32:24 -04:00
|
|
|
})
|
2018-05-23 14:26:35 -04:00
|
|
|
|
|
|
|
|
_, err := th.App.GetPluginStatuses()
|
2018-11-20 08:52:51 -05:00
|
|
|
require.NotNil(t, err)
|
2022-07-28 11:05:03 -04:00
|
|
|
require.EqualError(t, err, "GetPluginStatuses: Plugins have been disabled. Please check your logs for details.")
|
2018-05-23 14:26:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestGetPluginStatuses(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2020-07-13 13:34:05 -04:00
|
|
|
th := Setup(t)
|
2018-05-23 14:26:35 -04:00
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
pluginStatuses, err := th.App.GetPluginStatuses()
|
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
require.NotNil(t, pluginStatuses)
|
2018-03-13 10:32:24 -04:00
|
|
|
}
|
2019-07-18 14:05:53 -04:00
|
|
|
|
|
|
|
|
func TestPluginSync(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2025-06-24 14:11:02 -04:00
|
|
|
path, _ := fileutils.FindDir("tests")
|
|
|
|
|
|
|
|
|
|
th := SetupConfig(t, func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.SignaturePublicKeyFiles = []string{
|
|
|
|
|
filepath.Join(path, "development-private-key.asc"),
|
|
|
|
|
}
|
|
|
|
|
})
|
2019-07-18 14:05:53 -04:00
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
Description string
|
|
|
|
|
ConfigFunc func(cfg *model.Config)
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
"local",
|
|
|
|
|
func(cfg *model.Config) {
|
2024-08-05 23:45:00 -04:00
|
|
|
cfg.FileSettings.DriverName = model.NewPointer(model.ImageDriverLocal)
|
2019-07-18 14:05:53 -04:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"s3",
|
|
|
|
|
func(cfg *model.Config) {
|
|
|
|
|
s3Host := os.Getenv("CI_MINIO_HOST")
|
|
|
|
|
if s3Host == "" {
|
2019-08-02 17:46:32 -04:00
|
|
|
s3Host = "localhost"
|
2019-07-18 14:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s3Port := os.Getenv("CI_MINIO_PORT")
|
|
|
|
|
if s3Port == "" {
|
2019-11-18 12:40:49 -05:00
|
|
|
s3Port = "9000"
|
2019-07-18 14:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s3Endpoint := fmt.Sprintf("%s:%s", s3Host, s3Port)
|
2024-08-05 23:45:00 -04:00
|
|
|
cfg.FileSettings.DriverName = model.NewPointer(model.ImageDriverS3)
|
|
|
|
|
cfg.FileSettings.AmazonS3AccessKeyId = model.NewPointer(model.MinioAccessKey)
|
|
|
|
|
cfg.FileSettings.AmazonS3SecretAccessKey = model.NewPointer(model.MinioSecretKey)
|
|
|
|
|
cfg.FileSettings.AmazonS3Bucket = model.NewPointer(model.MinioBucket)
|
|
|
|
|
cfg.FileSettings.AmazonS3PathPrefix = model.NewPointer("")
|
|
|
|
|
cfg.FileSettings.AmazonS3Endpoint = model.NewPointer(s3Endpoint)
|
|
|
|
|
cfg.FileSettings.AmazonS3Region = model.NewPointer("")
|
|
|
|
|
cfg.FileSettings.AmazonS3SSL = model.NewPointer(false)
|
2019-07-18 14:05:53 -04:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
|
t.Run(testCase.Description, func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = true
|
2020-01-15 13:38:55 -05:00
|
|
|
testCase.ConfigFunc(cfg)
|
2019-07-18 14:05:53 -04:00
|
|
|
})
|
|
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
require.NotNil(t, env)
|
2019-07-18 14:05:53 -04:00
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
t.Run("new bundle in the file store", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.RequirePluginSignature = false
|
|
|
|
|
})
|
2019-07-18 14:05:53 -04:00
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
fileReader, err := os.Open(filepath.Join(path, "testplugin.tar.gz"))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
defer fileReader.Close()
|
2019-07-18 14:05:53 -04:00
|
|
|
|
2021-05-11 06:00:44 -04:00
|
|
|
_, appErr := th.App.WriteFile(fileReader, getBundleStorePath("testplugin"))
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
2019-07-18 14:05:53 -04:00
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
appErr = th.App.SyncPlugins()
|
|
|
|
|
checkNoError(t, appErr)
|
2019-07-18 14:05:53 -04:00
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
// Check if installed
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-01-15 13:38:55 -05:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, pluginStatus[0].PluginId, "testplugin")
|
|
|
|
|
})
|
2019-07-18 14:05:53 -04:00
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
t.Run("bundle removed from the file store", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.RequirePluginSignature = false
|
|
|
|
|
})
|
2019-11-18 19:02:41 -05:00
|
|
|
|
2021-05-11 06:00:44 -04:00
|
|
|
appErr := th.App.RemoveFile(getBundleStorePath("testplugin"))
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
appErr = th.App.SyncPlugins()
|
|
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
// Check if removed
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-01-15 13:38:55 -05:00
|
|
|
require.Empty(t, pluginStatus)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("plugin signatures required, no signature", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.RequirePluginSignature = true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
pluginFileReader, err := os.Open(filepath.Join(path, "testplugin.tar.gz"))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
defer pluginFileReader.Close()
|
2021-05-11 06:00:44 -04:00
|
|
|
_, appErr := th.App.WriteFile(pluginFileReader, getBundleStorePath("testplugin"))
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
appErr = th.App.SyncPlugins()
|
|
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-01-15 13:38:55 -05:00
|
|
|
require.Len(t, pluginStatus, 0)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("plugin signatures required, wrong signature", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.RequirePluginSignature = true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
signatureFileReader, err := os.Open(filepath.Join(path, "testplugin2.tar.gz.sig"))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
defer signatureFileReader.Close()
|
2021-05-11 06:00:44 -04:00
|
|
|
_, appErr := th.App.WriteFile(signatureFileReader, getSignatureStorePath("testplugin"))
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
appErr = th.App.SyncPlugins()
|
|
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-01-15 13:38:55 -05:00
|
|
|
require.Len(t, pluginStatus, 0)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("plugin signatures required, correct signature", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.RequirePluginSignature = true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
signatureFileReader, err := os.Open(filepath.Join(path, "testplugin.tar.gz.sig"))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
defer signatureFileReader.Close()
|
2025-06-24 14:11:02 -04:00
|
|
|
_, appErr := th.App.WriteFile(signatureFileReader, getSignatureStorePath("testplugin"))
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
appErr = th.App.SyncPlugins()
|
|
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-01-15 13:38:55 -05:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, pluginStatus[0].PluginId, "testplugin")
|
|
|
|
|
|
|
|
|
|
appErr = th.App.DeletePublicKey("pub_key")
|
|
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
2022-12-21 14:10:26 -05:00
|
|
|
appErr = th.App.ch.RemovePlugin("testplugin")
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
2019-11-18 19:02:41 -05:00
|
|
|
})
|
2019-07-18 14:05:53 -04:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-15 13:38:55 -05:00
|
|
|
|
2021-12-17 01:39:10 -05:00
|
|
|
// See https://github.com/mattermost/mattermost-server/issues/19189
|
|
|
|
|
func TestChannelsPluginsInit(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2021-12-17 01:39:10 -05:00
|
|
|
th := Setup(t)
|
|
|
|
|
|
|
|
|
|
runNoPanicTest := func(t *testing.T) {
|
|
|
|
|
path, _ := fileutils.FindDir("tests")
|
|
|
|
|
|
|
|
|
|
require.NotPanics(t, func() {
|
2023-10-06 16:43:21 -04:00
|
|
|
th.Server.Channels().initPlugins(th.Context, path, path)
|
2021-12-17 01:39:10 -05:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Run("no panics when plugins enabled", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
runNoPanicTest(t)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("no panics when plugins disabled", func(t *testing.T) {
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = false
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
runNoPanicTest(t)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-27 09:22:20 -04:00
|
|
|
func TestSyncPluginsActiveState(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2020-08-27 09:22:20 -04:00
|
|
|
th := Setup(t)
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
require.NotNil(t, env)
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.RequirePluginSignature = false
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
path, _ := fileutils.FindDir("tests")
|
|
|
|
|
fileReader, err := os.Open(filepath.Join(path, "testplugin.tar.gz"))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
defer fileReader.Close()
|
|
|
|
|
|
2021-05-11 06:00:44 -04:00
|
|
|
_, appErr := th.App.WriteFile(fileReader, getBundleStorePath("testplugin"))
|
2020-08-27 09:22:20 -04:00
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
// Sync with file store so the plugin environment has access to this plugin.
|
|
|
|
|
appErr = th.App.SyncPlugins()
|
|
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
// Verify the plugin was installed and set to deactivated.
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-08-27 09:22:20 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, pluginStatus[0].PluginId, "testplugin")
|
|
|
|
|
require.Equal(t, pluginStatus[0].State, model.PluginStateNotRunning)
|
|
|
|
|
|
|
|
|
|
// Enable plugin by setting setting config. This implicitly calls SyncPluginsActiveState through a config listener.
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Verify the plugin was activated due to config change.
|
|
|
|
|
pluginStatus, err = env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-08-27 09:22:20 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, pluginStatus[0].PluginId, "testplugin")
|
|
|
|
|
require.Equal(t, pluginStatus[0].State, model.PluginStateRunning)
|
|
|
|
|
|
|
|
|
|
// Disable plugin by setting config. This implicitly calls SyncPluginsActiveState through a config listener.
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: false}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Verify the plugin was deactivated due to config change.
|
|
|
|
|
pluginStatus, err = env.Statuses()
|
2021-02-16 06:00:01 -05:00
|
|
|
require.NoError(t, err)
|
2020-08-27 09:22:20 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, pluginStatus[0].PluginId, "testplugin")
|
|
|
|
|
require.Equal(t, pluginStatus[0].State, model.PluginStateNotRunning)
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-11 03:41:11 -04:00
|
|
|
func TestPluginPanicLogs(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2020-03-11 03:41:11 -04:00
|
|
|
t.Run("should panic", func(t *testing.T) {
|
2025-11-12 07:00:51 -05:00
|
|
|
th := Setup(t).InitBasic(t)
|
2021-05-11 06:00:44 -04:00
|
|
|
|
2020-03-11 03:41:11 -04:00
|
|
|
tearDown, _, _ := SetAppEnvironmentWithPlugins(t, []string{
|
|
|
|
|
`
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2023-06-11 01:24:35 -04:00
|
|
|
"github.com/mattermost/mattermost/server/public/plugin"
|
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
2020-03-11 03:41:11 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type MyPlugin struct {
|
|
|
|
|
plugin.MattermostPlugin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
|
|
|
|
|
panic("some text from panic")
|
|
|
|
|
return nil, ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
plugin.ClientMain(&MyPlugin{})
|
|
|
|
|
}
|
|
|
|
|
`,
|
2021-05-11 06:00:44 -04:00
|
|
|
}, th.App, th.NewPluginAPI)
|
2020-03-11 03:41:11 -04:00
|
|
|
|
|
|
|
|
post := &model.Post{
|
|
|
|
|
UserId: th.BasicUser.Id,
|
|
|
|
|
ChannelId: th.BasicChannel.Id,
|
|
|
|
|
Message: "message_",
|
|
|
|
|
CreateAt: model.GetMillis() - 10000,
|
|
|
|
|
}
|
2024-10-22 10:00:26 -04:00
|
|
|
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
|
2020-03-11 03:41:11 -04:00
|
|
|
assert.Nil(t, err)
|
2021-08-17 16:08:04 -04:00
|
|
|
|
|
|
|
|
th.TestLogger.Flush()
|
|
|
|
|
|
2020-12-15 08:49:53 -05:00
|
|
|
// We shutdown plugins first so that the read on the log buffer is race-free.
|
2022-12-21 14:10:26 -05:00
|
|
|
th.App.ch.ShutDownPlugins()
|
2020-12-15 08:49:53 -05:00
|
|
|
tearDown()
|
2020-03-11 03:41:11 -04:00
|
|
|
|
2021-08-17 16:08:04 -04:00
|
|
|
testlib.AssertLog(t, th.LogBuffer, mlog.LvlDebug.Name, "panic: some text from panic")
|
2020-03-11 03:41:11 -04:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-21 10:55:57 -04:00
|
|
|
func TestPluginStatusActivateError(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2022-07-21 10:55:57 -04:00
|
|
|
t.Run("should return error from OnActivate in plugin statuses", func(t *testing.T) {
|
2025-11-12 07:00:51 -05:00
|
|
|
th := Setup(t).InitBasic(t)
|
2022-07-21 10:55:57 -04:00
|
|
|
|
|
|
|
|
pluginSource := `
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
|
2023-06-11 01:24:35 -04:00
|
|
|
"github.com/mattermost/mattermost/server/public/plugin"
|
2022-07-21 10:55:57 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type MyPlugin struct {
|
|
|
|
|
plugin.MattermostPlugin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *MyPlugin) OnActivate() error {
|
|
|
|
|
return errors.New("sample error")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
plugin.ClientMain(&MyPlugin{})
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
tearDown, _, _ := SetAppEnvironmentWithPlugins(t, []string{pluginSource}, th.App, th.NewPluginAPI)
|
|
|
|
|
defer tearDown()
|
|
|
|
|
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, "sample error", pluginStatus[0].Error)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-22 08:35:16 -05:00
|
|
|
type byID []*plugin.PrepackagedPlugin
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
2024-01-22 08:35:16 -05:00
|
|
|
func (a byID) Len() int { return len(a) }
|
|
|
|
|
func (a byID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
|
func (a byID) Less(i, j int) bool { return a[i].Manifest.Id < a[j].Manifest.Id }
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
type pluginStatusById model.PluginStatuses
|
|
|
|
|
|
|
|
|
|
func (a pluginStatusById) Len() int { return len(a) }
|
|
|
|
|
func (a pluginStatusById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
|
func (a pluginStatusById) Less(i, j int) bool { return a[i].PluginId < a[j].PluginId }
|
|
|
|
|
|
|
|
|
|
func TestProcessPrepackagedPlugins(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2025-06-24 14:11:02 -04:00
|
|
|
testsPath, found := fileutils.FindDir("tests")
|
|
|
|
|
require.True(t, found, "failed to find tests directory")
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
setup := func(t *testing.T) *TestHelper {
|
|
|
|
|
t.Helper()
|
2020-01-15 13:38:55 -05:00
|
|
|
|
2025-06-24 14:11:02 -04:00
|
|
|
th := SetupConfig(t, func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.SignaturePublicKeyFiles = []string{
|
|
|
|
|
filepath.Join(testsPath, "development-private-key.asc"),
|
|
|
|
|
}
|
|
|
|
|
})
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
// Make a prepackaged_plugins directory for use with the tests.
|
2025-05-30 07:58:26 -04:00
|
|
|
err := os.Mkdir(filepath.Join(th.tempWorkspace, prepackagedPluginsDir), os.ModePerm)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.Enable = true
|
|
|
|
|
*cfg.PluginSettings.EnableRemoteMarketplace = false
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return th
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initPlugins := func(t *testing.T, th *TestHelper) ([]*plugin.PrepackagedPlugin, []*plugin.PrepackagedPlugin) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
appErr := th.App.ch.syncPlugins()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.Nil(t, appErr)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
err := th.App.ch.processPrepackagedPlugins(filepath.Join(th.tempWorkspace, prepackagedPluginsDir))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.NoError(t, err)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
plugins, transitionalPlugins := env.PrepackagedPlugins(), env.TransitionallyPrepackagedPlugins()
|
|
|
|
|
th.App.ch.persistTransitionallyPrepackagedPlugins()
|
|
|
|
|
|
|
|
|
|
return plugins, transitionalPlugins
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin := func(t *testing.T, th *TestHelper, filename string) {
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Helper()
|
2020-01-15 13:38:55 -05:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
err := testlib.CopyFile(filepath.Join(testsPath, filename), filepath.Join(th.tempWorkspace, prepackagedPluginsDir, filename))
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
err = testlib.CopyFile(filepath.Join(testsPath, fmt.Sprintf("%s.sig", filename)), filepath.Join(th.tempWorkspace, prepackagedPluginsDir, fmt.Sprintf("%s.sig", filename)))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsFilestorePlugin := func(t *testing.T, th *TestHelper, bundleFilename, pluginID string) {
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Helper()
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
err := testlib.CopyFile(filepath.Join(testsPath, bundleFilename), filepath.Join(*th.App.Config().FileSettings.Directory, fmt.Sprintf("plugins/%s.tar.gz", pluginID)))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.NoError(t, err)
|
2025-05-30 07:58:26 -04:00
|
|
|
err = testlib.CopyFile(filepath.Join(testsPath, fmt.Sprintf("%s.sig", bundleFilename)), filepath.Join(*th.App.Config().FileSettings.Directory, fmt.Sprintf("plugins/%s.tar.gz.sig", pluginID)))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expectPrepackagedPlugin := func(t *testing.T, pluginID, version string, actual *plugin.PrepackagedPlugin) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
require.Equal(t, pluginID, actual.Manifest.Id)
|
2025-06-24 14:11:02 -04:00
|
|
|
require.NotEmpty(t, actual.SignaturePath, "testplugin has no signature")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Equal(t, version, actual.Manifest.Version)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore := func(t *testing.T, th *TestHelper, pluginID, version string) {
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Helper()
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
bundlePath := filepath.Join(*th.App.Config().FileSettings.Directory, fmt.Sprintf("plugins/%s.tar.gz", pluginID))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
require.FileExists(t, bundlePath)
|
2025-05-30 07:58:26 -04:00
|
|
|
require.FileExists(t, filepath.Join(*th.App.Config().FileSettings.Directory, fmt.Sprintf("plugins/%s.tar.gz.sig", pluginID)))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
// Verify the version recorded in the Manifest
|
|
|
|
|
f, err := os.Open(bundlePath)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
uncompressedStream, err := gzip.NewReader(f)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
tarReader := tar.NewReader(uncompressedStream)
|
|
|
|
|
|
|
|
|
|
var manifest model.Manifest
|
|
|
|
|
for {
|
|
|
|
|
header, err := tarReader.Next()
|
|
|
|
|
if err == io.EOF {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
t.Log(header.Name)
|
|
|
|
|
if header.Typeflag == tar.TypeReg && filepath.Base(header.Name) == "plugin.json" {
|
|
|
|
|
manifestReader := json.NewDecoder(tarReader)
|
|
|
|
|
err = manifestReader.Decode(&manifest)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.Equal(t, pluginID, manifest.Id, "failed to find manifest")
|
|
|
|
|
require.Equal(t, version, manifest.Version)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore := func(t *testing.T, th *TestHelper, pluginID string) {
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Helper()
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
require.NoFileExists(t, filepath.Join(*th.App.Config().FileSettings.Directory, fmt.Sprintf("plugins/%s.tar.gz", pluginID)))
|
|
|
|
|
require.NoFileExists(t, filepath.Join(*th.App.Config().FileSettings.Directory, fmt.Sprintf("plugins/%s.tar.gz.sig", pluginID)))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expectPluginStatus := func(t *testing.T, pluginID, version string, actual *model.PluginStatus) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
require.Equal(t, pluginID, actual.PluginId)
|
|
|
|
|
require.Equal(t, version, actual.Version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Run("single plugin automatically installed since enabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 1, "expected one prepackaged plugin")
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, pluginStatus, 1)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPluginStatus(t, "testplugin", "0.0.1", pluginStatus[0])
|
2020-01-15 13:38:55 -05:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Run("single plugin, not automatically installed since not enabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 1, "expected one prepackaged plugin")
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Empty(t, pluginStatus, 0)
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("single plugin, not automatically installed despite enabled since automatic prepackaged plugins disabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
2020-01-15 13:38:55 -05:00
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = false
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 1, "expected one prepackaged plugin")
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Empty(t, pluginStatus, 0)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Run("multiple plugins, some automatically installed since enabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
cfg.PluginSettings.PluginStates["testplugin2"] = &model.PluginState{Enable: true}
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin2.tar.gz")
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
pluginStatus, err := env.Statuses()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
expectPluginStatus(t, "testplugin2", "1.2.3", pluginStatus[0])
|
2020-01-15 13:38:55 -05:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("multiple plugins, one previously installed, all now installed", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsFilestorePlugin(t, th, "testplugin.tar.gz", "testplugin")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin2"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin2.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
sort.Sort(pluginStatusById(pluginStatus))
|
|
|
|
|
|
|
|
|
|
require.Len(t, pluginStatus, 2)
|
|
|
|
|
expectPluginStatus(t, "testplugin", "0.0.1", pluginStatus[0])
|
|
|
|
|
expectPluginStatus(t, "testplugin2", "1.2.3", pluginStatus[1])
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore(t, th, "testplugin", "0.0.1")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Run("multiple plugins, one previously installed and now upgraded, all now installed", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsFilestorePlugin(t, th, "testplugin.tar.gz", "testplugin")
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin2"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin-v0.0.2.tar.gz")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin2.tar.gz")
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
2025-05-30 07:58:26 -04:00
|
|
|
err := th.App.ch.processPrepackagedPlugins(filepath.Join(th.tempWorkspace, prepackagedPluginsDir))
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.2", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
pluginStatus, err := env.Statuses()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
sort.Sort(pluginStatusById(pluginStatus))
|
|
|
|
|
|
|
|
|
|
require.Len(t, pluginStatus, 2)
|
|
|
|
|
expectPluginStatus(t, "testplugin", "0.0.2", pluginStatus[0])
|
|
|
|
|
expectPluginStatus(t, "testplugin2", "1.2.3", pluginStatus[1])
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore(t, th, "testplugin", "0.0.1")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("multiple plugins, one previously installed but prepackaged is older, all now installed", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsFilestorePlugin(t, th, "testplugin-v0.0.2.tar.gz", "testplugin")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin2"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin2.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
sort.Sort(pluginStatusById(pluginStatus))
|
|
|
|
|
|
|
|
|
|
require.Len(t, pluginStatus, 2)
|
|
|
|
|
expectPluginStatus(t, "testplugin", "0.0.2", pluginStatus[0])
|
|
|
|
|
expectPluginStatus(t, "testplugin2", "1.2.3", pluginStatus[1])
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore(t, th, "testplugin", "0.0.2")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("multiple plugins, not automatically installed despite enabled since automatic prepackaged plugins disabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = false
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin2"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin2.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Len(t, pluginStatus, 0)
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Run("removing a prepackaged plugin leaves it disabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin2"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin2.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
sort.Sort(pluginStatusById(pluginStatus))
|
|
|
|
|
|
|
|
|
|
require.Len(t, pluginStatus, 2)
|
|
|
|
|
require.Equal(t, "testplugin", pluginStatus[0].PluginId)
|
|
|
|
|
require.Equal(t, "testplugin2", pluginStatus[1].PluginId)
|
|
|
|
|
|
|
|
|
|
appErr := th.App.ch.RemovePlugin("testplugin")
|
2020-01-15 13:38:55 -05:00
|
|
|
checkNoError(t, appErr)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err = env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
require.Equal(t, "testplugin2", pluginStatus[0].PluginId)
|
|
|
|
|
|
|
|
|
|
plugins, transitionalPlugins = initPlugins(t, th)
|
|
|
|
|
require.Len(t, plugins, 2, "expected two prepackaged plugins")
|
2024-01-22 08:35:16 -05:00
|
|
|
sort.Sort(byID(plugins))
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", plugins[0])
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin2", "1.2.3", plugins[1])
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err = env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
expectPluginStatus(t, "testplugin2", "1.2.3", pluginStatus[0])
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
t.Run("single transitional plugin automatically installed and persisted since enabled", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
|
|
|
|
oldTransitionallyPrepackagedPlugins := append([]string{}, transitionallyPrepackagedPlugins...)
|
|
|
|
|
transitionallyPrepackagedPlugins = append(transitionallyPrepackagedPlugins, "testplugin")
|
|
|
|
|
defer func() {
|
|
|
|
|
transitionallyPrepackagedPlugins = oldTransitionallyPrepackagedPlugins
|
|
|
|
|
}()
|
|
|
|
|
|
2020-01-15 13:38:55 -05:00
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Empty(t, plugins)
|
|
|
|
|
require.Len(t, transitionalPlugins, 1)
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", transitionalPlugins[0])
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
expectPluginStatus(t, "testplugin", "0.0.1", pluginStatus[0])
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore(t, th, "testplugin", "0.0.1")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("single transitional plugin not persisted since already in filestore", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
2020-01-15 13:38:55 -05:00
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
oldTransitionallyPrepackagedPlugins := append([]string{}, transitionallyPrepackagedPlugins...)
|
|
|
|
|
transitionallyPrepackagedPlugins = append(transitionallyPrepackagedPlugins, "testplugin")
|
|
|
|
|
defer func() {
|
|
|
|
|
transitionallyPrepackagedPlugins = oldTransitionallyPrepackagedPlugins
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsFilestorePlugin(t, th, "testplugin.tar.gz", "testplugin")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Empty(t, plugins)
|
|
|
|
|
require.Empty(t, transitionalPlugins)
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
expectPluginStatus(t, "testplugin", "0.0.1", pluginStatus[0])
|
2020-01-15 13:38:55 -05:00
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore(t, th, "testplugin", "0.0.1")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("single transitional plugin persisted since newer than filestore", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
|
|
|
|
oldTransitionallyPrepackagedPlugins := append([]string{}, transitionallyPrepackagedPlugins...)
|
|
|
|
|
transitionallyPrepackagedPlugins = append(transitionallyPrepackagedPlugins, "testplugin")
|
|
|
|
|
defer func() {
|
|
|
|
|
transitionallyPrepackagedPlugins = oldTransitionallyPrepackagedPlugins
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsFilestorePlugin(t, th, "testplugin.tar.gz", "testplugin")
|
|
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin-v0.0.2.tar.gz")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
|
|
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Empty(t, plugins)
|
|
|
|
|
require.Len(t, transitionalPlugins, 1)
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.2", transitionalPlugins[0])
|
|
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
2020-01-15 13:38:55 -05:00
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Len(t, pluginStatus, 1)
|
|
|
|
|
expectPluginStatus(t, "testplugin", "0.0.2", pluginStatus[0])
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginInFilestore(t, th, "testplugin", "0.0.2")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("transitional plugins persisted only once", func(t *testing.T) {
|
|
|
|
|
th := setup(t)
|
|
|
|
|
env := th.App.GetPluginsEnvironment()
|
|
|
|
|
|
|
|
|
|
oldTransitionallyPrepackagedPlugins := append([]string{}, transitionallyPrepackagedPlugins...)
|
|
|
|
|
transitionallyPrepackagedPlugins = append(transitionallyPrepackagedPlugins, "testplugin")
|
|
|
|
|
defer func() {
|
|
|
|
|
transitionallyPrepackagedPlugins = oldTransitionallyPrepackagedPlugins
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
|
|
|
*cfg.PluginSettings.AutomaticPrepackagedPlugins = true
|
|
|
|
|
cfg.PluginSettings.PluginStates["testplugin"] = &model.PluginState{Enable: true}
|
|
|
|
|
})
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
copyAsPrepackagedPlugin(t, th, "testplugin.tar.gz")
|
2020-01-15 13:38:55 -05:00
|
|
|
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
plugins, transitionalPlugins := initPlugins(t, th)
|
|
|
|
|
require.Empty(t, plugins)
|
|
|
|
|
require.Len(t, transitionalPlugins, 1)
|
|
|
|
|
expectPrepackagedPlugin(t, "testplugin", "0.0.1", transitionalPlugins[0])
|
|
|
|
|
|
2025-04-11 04:42:16 -04:00
|
|
|
appErr := th.App.ch.RemovePlugin("testplugin")
|
|
|
|
|
require.Nil(t, appErr)
|
2020-01-15 13:38:55 -05:00
|
|
|
|
|
|
|
|
pluginStatus, err := env.Statuses()
|
|
|
|
|
require.NoError(t, err)
|
MM-53355: install transitionally prepackaged plugins to filestore (#24225)
* move plugin signature verification to caller
The semantics for when plugin signature validation is required are unique to the caller, so move this logic there instead of masking it, thus simplifying some of the downstream code.
* support transitionally prepacked plugins
Transitionally prepackaged plugins are prepackaged plugins slated for unpackaging in some future release. Like prepackaged plugins, they automatically install or upgrade if the server is configured to enable that plugin, but unlike prepackaged plugins they don't add to the marketplace to allow for offline installs. In fact, if unlisted from the marketplace and not already enabled via `config.json`, a transitionally prepackaged plugin is essentially hidden.
To ensure a smooth transition in the future release when this plugin is no longer prepackaged at all, transitionally prepackaged plugins are persisted to the filestore as if they had been installed by the enduser. On the next restart, even while the plugin is still transitionally prepackaged, the version in the filestore will take priority. It remains possible for a transitionally prepackaged plugin to upgrade (and once again persist) if we ship a newer version before dropping it altogether.
Some complexity arises in a multi-server cluster, primarily because we don't want to deal with multiple servers writing the same object to the filestore. This is probably fine for S3, but has undefined semantics for regular filesystems, especially with some customers backing their files on any number of different fileshare technologies. To simplify the complexity, only the cluster leader persists transitionally prepackaged plugins.
Unfortunately, this too is complicated, since on upgrade to the first version with the transitionally prepackaged plugin, there is no guarantee that server will be the leader. In fact, as all nodes restart, there is no guarantee that any newly started server will start as the leader. So the persistence has to happen in a job-like fashion. The migration system might work, except we want the ability to run this repeatedly as we add to (or update) these transitionally prepackaged plugins. We also want to minimize the overhead required from the server to juggle any of this.
As a consequence, the persistence of transitionally prepackaged plugins occurs on every cluster leader change. Each server will try at most once to persist its collection of transitionally prepackaged plugins, and newly started servers will see the plugins in the filestore and skip this step altogether.
The current set of transitionally prepackaged plugins include the following, but this is expected to change:
* focalboard
* complete list of transitionally prepackaged plugins
* update plugin_install.go docs
* updated test plugins
* unit test transitionally prepackged plugins
* try restoring original working directory
* Apply suggestions from code review
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
* clarify processPrepackagedPlugins comment
---------
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
2023-08-17 11:46:57 -04:00
|
|
|
require.Empty(t, pluginStatus, 0)
|
|
|
|
|
|
|
|
|
|
th.App.ch.persistTransitionallyPrepackagedPlugins()
|
|
|
|
|
|
2025-05-30 07:58:26 -04:00
|
|
|
expectPluginNotInFilestore(t, th, "testplugin")
|
|
|
|
|
expectPluginNotInFilestore(t, th, "testplugin2")
|
2020-01-15 13:38:55 -05:00
|
|
|
})
|
|
|
|
|
}
|
2022-05-10 13:29:48 -04:00
|
|
|
|
|
|
|
|
func TestGetPluginStateOverride(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
2022-05-10 13:29:48 -04:00
|
|
|
th := Setup(t)
|
|
|
|
|
|
|
|
|
|
t.Run("no override", func(t *testing.T) {
|
2022-12-21 14:10:26 -05:00
|
|
|
overrides, value := th.App.ch.getPluginStateOverride("focalboard")
|
2022-05-10 13:29:48 -04:00
|
|
|
require.False(t, overrides)
|
|
|
|
|
require.False(t, value)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("apps override", func(t *testing.T) {
|
|
|
|
|
t.Run("without enabled flag", func(t *testing.T) {
|
2022-12-21 14:10:26 -05:00
|
|
|
overrides, value := th.App.ch.getPluginStateOverride("com.mattermost.apps")
|
2024-07-31 13:18:30 -04:00
|
|
|
require.True(t, overrides)
|
|
|
|
|
require.False(t, value)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("with enabled flag set to true", func(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
|
|
|
|
th2 := SetupConfig(t, func(cfg *model.Config) {
|
|
|
|
|
cfg.FeatureFlags.AppsEnabled = true
|
|
|
|
|
})
|
2024-07-31 13:18:30 -04:00
|
|
|
|
|
|
|
|
overrides, value := th2.App.ch.getPluginStateOverride("com.mattermost.apps")
|
2022-05-10 13:29:48 -04:00
|
|
|
require.False(t, overrides)
|
|
|
|
|
require.False(t, value)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("with enabled flag set to false", func(t *testing.T) {
|
2025-05-30 07:58:26 -04:00
|
|
|
mainHelper.Parallel(t)
|
|
|
|
|
th2 := SetupConfig(t, func(cfg *model.Config) {
|
|
|
|
|
cfg.FeatureFlags.AppsEnabled = false
|
|
|
|
|
})
|
2022-05-10 13:29:48 -04:00
|
|
|
|
2022-12-21 14:10:26 -05:00
|
|
|
overrides, value := th2.App.ch.getPluginStateOverride("com.mattermost.apps")
|
2022-05-10 13:29:48 -04:00
|
|
|
require.True(t, overrides)
|
|
|
|
|
require.False(t, value)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|