Skip to content

Commit

Permalink
[MM-36050] Change enterprise license check for installing multiple Ji…
Browse files Browse the repository at this point in the history
…ra instances to allow for E20, Professional, and Enterprise (#775)

* remove checks for enterprise license when installing multiple instances

* Update docs referencing multi server requiring an enterprise license

* Revert "remove checks for enterprise license when installing multiple instances"

This reverts commit b303882.

* remove workflow functionality

* update dependencies

* go mod tidy

* check for E10 or better license

* update license error messages and tests

* update license and docs

* change license check to exclude e10

* fix test

* go mod tidy

* mention other SKUs

* clarify which Enterprise versions are supported, and explain developer mode

* change error string

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
  • Loading branch information
mickmister and mattermod committed Aug 20, 2021
1 parent 99a8136 commit 6678cae
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 55 deletions.
2 changes: 1 addition & 1 deletion docs/README.md
Expand Up @@ -6,4 +6,4 @@ This plugin supports a two-way integration between Mattermost and Jira. For a st

This plugin supports Jira Core and Jira Software products for Server, Data Center, and Cloud platforms. It has been tested with versions 7 and 8.

**Support for multiple Jira instances is supported from Jira 3.0 for Mattermost Enterprise Edition E20 and configured using [Administrator Slash Commands](https://mattermost.gitbook.io/plugin-jira/administrator-guide/administrator-slash-commands).**
**Support for multiple Jira instances is available in Jira plugin v3.0 and later. The feature is configured using [Administrator Slash Commands](https://mattermost.gitbook.io/plugin-jira/administrator-guide/administrator-slash-commands). Note that versions v3.0.0 and v3.0.1 of the plugin require an E20 Enterprise license to use this feature. The feature is now available for Mattermost E20, Professional, and Enterprise licenses.**
2 changes: 2 additions & 0 deletions docs/development/environment.md
Expand Up @@ -10,4 +10,6 @@ This plugin supports both Jira Server (self-hosted) and Jira Cloud instances. Th

To test your changes against a local instance of Jira Server, you need [Docker](https://docs.docker.com/install) installed, then you can use the `docker-compose.yml` file in this repository to create a Jira instance. Simply run `docker-compose up` in the directory of the repository, and a new Jira server should start up and be available at http://localhost:8080. It can take a few minutes to start up due to Jira Server's startup processes. If the container fails to start with `exit code 137`, you may need to increase the amount of RAM you are allowing docker to use.

If you are contributing to a feature that requires multiple Jira instances to be installed, please enable [ServiceSettings.EnableDeveloper](https://docs.mattermost.com/configure/configuration-settings.html#enable-developer-mode) in your server's config in order to circumvent the Enterprise license requirement.

To test your changes against a Jira Cloud instance, we recommend starting a 14-day trial, if you don't have a Jira project to test against. More information can be found here: https://www.atlassian.com/software/jira/try.
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -127,6 +127,7 @@ github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwj
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/blevesearch/bleve v1.0.14/go.mod h1:e/LJTr+E7EaoVdkQZTfoz7dt4KoDNvDbLb8MSKuNTLQ=
github.com/blevesearch/blevex v1.0.0/go.mod h1:2rNVqoG2BZI8t1/P1awgTKnGlx5MP9ZbtEciQaNhswc=
Expand Down Expand Up @@ -877,6 +878,7 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
Expand Down
4 changes: 2 additions & 2 deletions readme.md
Expand Up @@ -2,7 +2,7 @@

This plugin supports a two-way integration between Mattermost and Jira. Jira Core and Jira Software products, for Server, Data Center, and Cloud platforms are supported. It has been tested with versions 7 and 8.

From v3.0 of this plugin, support for multiple Jira instances is offered for Mattermost Enterprise Edition E20.
For versions v3.0 and later of this plugin, support for multiple Jira instances is offered for Mattermost E20, Professionsal, and Enterprise Edition. Note that for versions v3.0.0 and v3.0.1 of this plugin, an E20 license is required to set up multiple Jira instances.

Visit our [Jira Plugin Documentation](https://mattermost.gitbook.io/jira-plugin/) for guidance on installation, configuration, and usage.

Expand All @@ -20,4 +20,4 @@ This repository is licensed under the Apache 2.0 License, except for the [server

## Development

This plugin contains both a server and web app portion. Read our documentation about the [Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Developer Setup](https://developers.mattermost.com/extend/plugins/developer-setup/) for more information about developing and extending plugins.
Read our [development docs](https://mattermost.gitbook.io/plugin-jira/development/environment) for this project, as well as the [Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Developer Setup](https://developers.mattermost.com/extend/plugins/developer-setup/) documentation for more information about developing and extending plugins.
2 changes: 1 addition & 1 deletion server/command.go
Expand Up @@ -801,7 +801,7 @@ func executeInstanceInstallCloud(p *Plugin, c *plugin.Context, header *model.Com
instances, _ := p.instanceStore.LoadInstances()
if !p.enterpriseChecker.HasEnterpriseFeatures() {
if instances != nil && len(instances.IDs()) > 0 {
return p.responsef(header, "You need a valid Mattermost Enterprise E20 License to install multiple Jira instances")
return p.responsef(header, licenseErrorString)
}
}

Expand Down
5 changes: 2 additions & 3 deletions server/command_test.go
Expand Up @@ -348,12 +348,11 @@ func TestPlugin_ExecuteCommand_Installation(t *testing.T) {
isSendEphemeralPostCalled := false

// add valid license
trueValue := true
var license model.License
license.Features = &model.Features{}
license.Features.EnterprisePlugins = &trueValue
license.SkuShortName = "professional"

api.On("GetLicense").Return(&license)
api.On("GetConfig").Return(&model.Config{})
api.On("RegisterCommand", mock.Anything).Return(nil)
api.On("GetBundlePath").Return("", nil)
api.On("SendEphemeralPost", mock.AnythingOfType("string"), mock.AnythingOfType("*model.Post")).Run(func(args mock.Arguments) {
Expand Down
16 changes: 8 additions & 8 deletions server/enterprise/LICENSE
Expand Up @@ -5,19 +5,19 @@ With regard to the Mattermost Software:

This software and associated documentation files (the "Software") may only be
used in production, if you (and any entity that you represent) have agreed to,
and are in compliance with, the Mattermost Terms of Service, available at
https://mattermost.com/enterprise-edition-terms/ (the “EE Terms”), or other
agreement governing the use of the Software, as agreed by you and Mattermost,
and otherwise have a valid Mattermost Enterprise E20 subscription for the
correct number of user seats. Subject to the foregoing sentence, you are free
and are in compliance with all of the following: (a) the Mattermost Terms of Service, available at
https://mattermost.com/enterprise-edition-terms/ (the “EE Terms”), (b) any other
agreement(s) governing the use of the Software, as agreed upon by you and Mattermost,
and (c) you otherwise have a valid license or Subscription for the
correct number of Registered Authorized Users of the Software. Subject to the foregoing, you are free
to modify this Software and publish patches to the Software. You agree that
Mattermost and/or its licensors (as applicable) retain all right, title and
interest in and to all such modifications and/or patches, and all such
modifications and/or patches may only be used, copied, modified, displayed,
distributed, or otherwise exploited with a valid Mattermost Enterprise E20
Edition subscription for the correct number of user seats. Notwithstanding
distributed, or otherwise exploited with a valid license or Subscription for the correct number of
Registered Authorized Users of the Software. Notwithstanding
the foregoing, you may copy and modify the Software for development and testing
purposes, without requiring a subscription. You agree that Mattermost and/or
purposes, without requiring a valid license or Subscription. You agree that Mattermost and/or
its licensors (as applicable) retain all right, title and interest in and to
all such modifications. You are not granted any other rights beyond what is
expressly stated herein. Subject to the foregoing, it is forbidden to copy,
Expand Down
26 changes: 12 additions & 14 deletions server/enterprise/license.go
@@ -1,6 +1,7 @@
package enterprise

import (
pluginapi "github.com/mattermost/mattermost-plugin-api"
"github.com/mattermost/mattermost-server/v5/model"
)

Expand All @@ -14,6 +15,7 @@ type enterpriseChecker struct {

type PluginAPI interface {
GetLicense() *model.License
GetConfig() *model.Config
}

func NewEnterpriseChecker(api PluginAPI) Checker {
Expand All @@ -22,23 +24,19 @@ func NewEnterpriseChecker(api PluginAPI) Checker {
}
}

const (
e20 = "E20"
professional = "professional"
enterprise = "enterprise"
)

func (e *enterpriseChecker) HasEnterpriseFeatures() bool {
config := e.api.GetConfig()
license := e.api.GetLicense()
if license == nil {
return false
}

if license.Features == nil {
return false
}

if license.Features.EnterprisePlugins == nil {
return false
}

if !*license.Features.EnterprisePlugins {
return false
if license != nil && (license.SkuShortName == e20 || license.SkuShortName == enterprise || license.SkuShortName == professional) {
return true
}

return true
return pluginapi.IsE20LicensedOrDevelopment(config, license)
}
4 changes: 3 additions & 1 deletion server/instances.go
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/mattermost/mattermost-plugin-jira/server/utils/types"
)

const licenseErrorString = "You need a valid Mattermost E20, Professional, or Enterprise License to install multiple Jira instances."

type Instances struct {
*types.ValueSet // of *InstanceCommon, not Instance
}
Expand Down Expand Up @@ -134,7 +136,7 @@ func (p *Plugin) InstallInstance(instance Instance) error {
func(instances *Instances) error {
if !p.enterpriseChecker.HasEnterpriseFeatures() {
if instances != nil && len(instances.IDs()) > 0 {
return errors.Errorf("You need a valid Mattermost Enterprise E20 License to install multiple Jira instances")
return errors.Errorf(licenseErrorString)
}
}

Expand Down
64 changes: 39 additions & 25 deletions server/instances_test.go
Expand Up @@ -21,58 +21,65 @@ func TestInstallInstance(t *testing.T) {
license *model.License
numInstances int
expectError bool
devEnabled bool
}{
"0 preinstalled valid license": {
"0 preinstalled, valid license": {
numInstances: 0,
expectError: false,
license: &model.License{
Features: &model.Features{
EnterprisePlugins: &trueValue,
},
SkuShortName: "professional",
},
},
"0 preinstalled nil license": {
"0 preinstalled, nil license": {
numInstances: 0,
expectError: false,
license: nil,
},
"0 preinstalled nil Features": {
numInstances: 0,
"1 preinstalled, professional license": {
numInstances: 1,
expectError: false,
license: &model.License{},
license: &model.License{
SkuShortName: "professional",
},
},
"0 preinstalled nil Features EnterprisePlugins": {
numInstances: 0,
"1 preinstalled, E10 license": {
numInstances: 1,
expectError: true,
license: &model.License{
SkuShortName: "E10",
},
},
"1 preinstalled, E20 license": {
numInstances: 1,
expectError: false,
license: &model.License{
Features: &model.Features{},
SkuShortName: "E20",
},
},
"1 preinstalled valid license": {
"1 preinstalled, enterprise license": {
numInstances: 1,
expectError: false,
license: &model.License{
Features: &model.Features{
EnterprisePlugins: &trueValue,
},
SkuShortName: "enterprise",
},
},
"1 preinstalled nil license": {
"1 preinstalled, cloud starter license. should have error": {
numInstances: 1,
expectError: true,
license: nil,
license: &model.License{
SkuShortName: "starter",
},
},
"1 preinstalled nil Features": {
"1 preinstalled, dev mode": {
numInstances: 1,
expectError: true,
license: &model.License{},
expectError: false,
license: nil,
devEnabled: true,
},
"1 preinstalled nil Features EnterprisePlugins": {
"1 preinstalled nil license": {
numInstances: 1,
expectError: true,
license: &model.License{
Features: &model.Features{},
},
license: nil,
},
} {
t.Run(name, func(t *testing.T) {
Expand All @@ -82,8 +89,15 @@ func TestInstallInstance(t *testing.T) {
p.enterpriseChecker = enterprise.NewEnterpriseChecker(api)
p.instanceStore = p.getMockInstanceStoreKV(tc.numInstances)

conf := &model.Config{}
if tc.devEnabled {
conf.ServiceSettings.EnableDeveloper = &trueValue
conf.ServiceSettings.EnableTesting = &trueValue
}

api.On("KVGet", mock.Anything).Return(mock.Anything, nil)
api.On("GetLicense").Return(tc.license)
api.On("GetConfig").Return(conf)
api.On("UnregisterCommand", mock.Anything, mock.Anything).Return(nil)
api.On("RegisterCommand", mock.Anything, mock.Anything).Return(nil)
api.On("PublishWebSocketEvent", mock.Anything, mock.Anything, mock.Anything)
Expand All @@ -103,7 +117,7 @@ func TestInstallInstance(t *testing.T) {
err = p.InstallInstance(testInstance0)
if tc.expectError {
assert.NotNil(t, err)
expected := "You need a valid Mattermost Enterprise E20 License to install multiple Jira instances"
expected := "You need a valid Mattermost E20, Professional, or Enterprise License to install multiple Jira instances."
assert.Equal(t, expected, err.Error())
} else {
assert.Nil(t, err)
Expand Down

0 comments on commit 6678cae

Please sign in to comment.