Additional Product APIs for Focalboard multi-product architecture (#20527)
* bump focalboard version; add services to product API * add API to fetch logger * import boards in same fashion as enterprise
Этот коммит содержится в:
3
.gitignore
поставляемый
3
.gitignore
поставляемый
@@ -22,8 +22,9 @@ config/config.json
|
|||||||
config/logging.json
|
config/logging.json
|
||||||
/plugins
|
/plugins
|
||||||
|
|
||||||
# Enterprise imports file
|
# Enterprise & products imports files
|
||||||
imports/imports.go
|
imports/imports.go
|
||||||
|
imports/boards_imports.go
|
||||||
|
|
||||||
# go.work file
|
# go.work file
|
||||||
go.work
|
go.work
|
||||||
|
|||||||
56
Makefile
56
Makefile
@@ -38,6 +38,8 @@ ifeq ($(BUILD_NUMBER),)
|
|||||||
BUILD_DATE := n/a
|
BUILD_DATE := n/a
|
||||||
BUILD_NUMBER := dev
|
BUILD_NUMBER := dev
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Enterprise
|
||||||
BUILD_ENTERPRISE_DIR ?= ../enterprise
|
BUILD_ENTERPRISE_DIR ?= ../enterprise
|
||||||
BUILD_ENTERPRISE ?= true
|
BUILD_ENTERPRISE ?= true
|
||||||
BUILD_ENTERPRISE_READY = false
|
BUILD_ENTERPRISE_READY = false
|
||||||
@@ -56,6 +58,8 @@ else
|
|||||||
BUILD_ENTERPRISE_READY = false
|
BUILD_ENTERPRISE_READY = false
|
||||||
BUILD_TYPE_NAME = team
|
BUILD_TYPE_NAME = team
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Webapp
|
||||||
BUILD_WEBAPP_DIR ?= ../mattermost-webapp
|
BUILD_WEBAPP_DIR ?= ../mattermost-webapp
|
||||||
BUILD_CLIENT = false
|
BUILD_CLIENT = false
|
||||||
BUILD_HASH_CLIENT = independent
|
BUILD_HASH_CLIENT = independent
|
||||||
@@ -70,6 +74,21 @@ else
|
|||||||
BUILD_CLIENT = false
|
BUILD_CLIENT = false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Boards
|
||||||
|
BUILD_BOARDS_DIR ?= ../focalboard
|
||||||
|
BUILD_BOARDS ?= true
|
||||||
|
BUILD_HASH_BOARDS = none
|
||||||
|
ifneq ($(wildcard $(BUILD_BOARDS_DIR)/.),)
|
||||||
|
ifeq ($(BUILD_BOARDS),true)
|
||||||
|
BUILD_BOARDS = true
|
||||||
|
BUILD_HASH_BOARDS = $(shell cd $(BUILD_BOARDS_DIR) && git rev-parse HEAD)
|
||||||
|
else
|
||||||
|
BUILD_BOARDS = false
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
BUILD_BOARDS = false
|
||||||
|
endif
|
||||||
|
|
||||||
# We need current user's UID for `run-haserver` so docker compose does not run server
|
# We need current user's UID for `run-haserver` so docker compose does not run server
|
||||||
# as root and mess up file permissions for devs. When running like this HOME will be blank
|
# as root and mess up file permissions for devs. When running like this HOME will be blank
|
||||||
# and docker will add '/', so we need to set the go-build cache location or we'll get
|
# and docker will add '/', so we need to set the go-build cache location or we'll get
|
||||||
@@ -91,6 +110,8 @@ LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildDate=$(BUIL
|
|||||||
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildHash=$(BUILD_HASH)"
|
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildHash=$(BUILD_HASH)"
|
||||||
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildHashEnterprise=$(BUILD_HASH_ENTERPRISE)"
|
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildHashEnterprise=$(BUILD_HASH_ENTERPRISE)"
|
||||||
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildEnterpriseReady=$(BUILD_ENTERPRISE_READY)"
|
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildEnterpriseReady=$(BUILD_ENTERPRISE_READY)"
|
||||||
|
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildHashBoards=$(BUILD_HASH_BOARDS)"
|
||||||
|
LDFLAGS += -X "github.com/mattermost/mattermost-server/v6/model.BuildBoards=$(BUILD_BOARDS)"
|
||||||
|
|
||||||
GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
|
GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
|
||||||
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
|
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
|
||||||
@@ -156,6 +177,17 @@ else
|
|||||||
ALL_PACKAGES=$(TE_PACKAGES)
|
ALL_PACKAGES=$(TE_PACKAGES)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Prepare optional Boards build.
|
||||||
|
BOARDS_PACKAGES=$(shell $(GO) list $(BUILD_BOARDS_DIR)/server/...)
|
||||||
|
ifeq ($(BUILD_BOARDS),true)
|
||||||
|
ALL_PACKAGES += $(BOARDS_PACKAGES)
|
||||||
|
IGNORE:=$(shell echo Boards build selected, preparing)
|
||||||
|
IGNORE:=$(shell rm -f imports/boards_imports.go)
|
||||||
|
IGNORE:=$(shell cp $(BUILD_BOARDS_DIR)/mattermost-plugin/product/imports/boards_imports.go imports/)
|
||||||
|
else
|
||||||
|
IGNORE:=$(shell rm -f imports/boards_imports.go)
|
||||||
|
endif
|
||||||
|
|
||||||
all: run ## Alias for 'run'.
|
all: run ## Alias for 'run'.
|
||||||
|
|
||||||
-include config.override.mk
|
-include config.override.mk
|
||||||
@@ -276,7 +308,12 @@ golangci-lint: ## Run golangci-lint on codebase
|
|||||||
$(GOBIN)/golangci-lint run ./...
|
$(GOBIN)/golangci-lint run ./...
|
||||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||||
ifneq ($(MM_NO_ENTERPRISE_LINT),true)
|
ifneq ($(MM_NO_ENTERPRISE_LINT),true)
|
||||||
$(GOBIN)/golangci-lint run ../enterprise/...
|
$(GOBIN)/golangci-lint run ../enterprise/...
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifeq ($(BUILD_BOARDS),true)
|
||||||
|
ifneq ($(MM_NO_BOARDS_LINT),true)
|
||||||
|
$(GOBIN)/golangci-lint run $(BUILD_BOARDS_DIR)/server/...
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -361,10 +398,10 @@ ifeq ($(BUILD_ENTERPRISE_READY),true)
|
|||||||
./scripts/prereq-check-enterprise.sh
|
./scripts/prereq-check-enterprise.sh
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
setup-go-work: export BUILD_ENTERPRISE_READY := $(BUILD_ENTERPRISE_READY)
|
||||||
|
setup-go-work: export BUILD_BOARDS := $(BUILD_BOARDS)
|
||||||
setup-go-work: ## Sets up your go.work file
|
setup-go-work: ## Sets up your go.work file
|
||||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
|
||||||
./scripts/setup_go_work.sh
|
./scripts/setup_go_work.sh
|
||||||
endif
|
|
||||||
|
|
||||||
check-style: golangci-lint plugin-checker vet ## Runs style/lint checks
|
check-style: golangci-lint plugin-checker vet ## Runs style/lint checks
|
||||||
|
|
||||||
@@ -396,6 +433,9 @@ gomodtidy:
|
|||||||
@if [ -f "imports/imports.go" ]; then \
|
@if [ -f "imports/imports.go" ]; then \
|
||||||
mv imports/imports.go imports/imports.go.orig; \
|
mv imports/imports.go imports/imports.go.orig; \
|
||||||
fi;
|
fi;
|
||||||
|
@if [ -f "imports/boards_imports.go" ]; then \
|
||||||
|
mv imports/boards_imports.go imports/boards_imports.go.orig; \
|
||||||
|
fi;
|
||||||
$(GO) mod tidy
|
$(GO) mod tidy
|
||||||
@if [ "$$(diff go.mod go.mod.orig)" != "" -o "$$(diff go.sum go.sum.orig)" != "" ]; then \
|
@if [ "$$(diff go.mod go.mod.orig)" != "" -o "$$(diff go.sum go.sum.orig)" != "" ]; then \
|
||||||
echo "go.mod/go.sum was modified. \ndiff- $$(diff go.mod go.mod.orig) \n$$(diff go.sum go.sum.orig) \nRun \"go mod tidy\"."; \
|
echo "go.mod/go.sum was modified. \ndiff- $$(diff go.mod go.mod.orig) \n$$(diff go.sum go.sum.orig) \nRun \"go mod tidy\"."; \
|
||||||
@@ -405,17 +445,25 @@ gomodtidy:
|
|||||||
@if [ -f "imports/imports.go.orig" ]; then \
|
@if [ -f "imports/imports.go.orig" ]; then \
|
||||||
mv imports/imports.go.orig imports/imports.go; \
|
mv imports/imports.go.orig imports/imports.go; \
|
||||||
fi;
|
fi;
|
||||||
|
@if [ -f "imports/boards_imports.go.orig" ]; then \
|
||||||
|
mv imports/boards_imports.go.orig imports/boards_imports.go; \
|
||||||
|
fi;
|
||||||
@rm go.*.orig;
|
@rm go.*.orig;
|
||||||
|
|
||||||
modules-tidy:
|
modules-tidy:
|
||||||
@if [ -f "imports/imports.go" ]; then \
|
@if [ -f "imports/imports.go" ]; then \
|
||||||
mv imports/imports.go imports/imports.go.orig; \
|
mv imports/imports.go imports/imports.go.orig; \
|
||||||
fi;
|
fi;
|
||||||
|
@if [ -f "imports/boards_imports.go" ]; then \
|
||||||
|
mv imports/boards_imports.go imports/boards_imports.go.orig; \
|
||||||
|
fi;
|
||||||
-$(GO) mod tidy
|
-$(GO) mod tidy
|
||||||
@if [ -f "imports/imports.go.orig" ]; then \
|
@if [ -f "imports/imports.go.orig" ]; then \
|
||||||
mv imports/imports.go.orig imports/imports.go; \
|
mv imports/imports.go.orig imports/imports.go; \
|
||||||
fi;
|
fi;
|
||||||
|
@if [ -f "imports/boards_imports.go.orig" ]; then \
|
||||||
|
mv imports/boards_imports.go.orig imports/boards_imports.go; \
|
||||||
|
fi;
|
||||||
|
|
||||||
test-server-pre: check-prereqs-enterprise start-docker go-junit-report do-cover-file ## Runs tests.
|
test-server-pre: check-prereqs-enterprise start-docker go-junit-report do-cover-file ## Runs tests.
|
||||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v6/app/imaging"
|
"github.com/mattermost/mattermost-server/v6/app/imaging"
|
||||||
"github.com/mattermost/mattermost-server/v6/app/request"
|
"github.com/mattermost/mattermost-server/v6/app/request"
|
||||||
"github.com/mattermost/mattermost-server/v6/config"
|
"github.com/mattermost/mattermost-server/v6/config"
|
||||||
@@ -20,19 +22,8 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/v6/services/imageproxy"
|
"github.com/mattermost/mattermost-server/v6/services/imageproxy"
|
||||||
"github.com/mattermost/mattermost-server/v6/shared/filestore"
|
"github.com/mattermost/mattermost-server/v6/shared/filestore"
|
||||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// configSvc is a consumer interface to work
|
|
||||||
// with any config related task with the server.
|
|
||||||
type configSvc interface {
|
|
||||||
Config() *model.Config
|
|
||||||
AddConfigListener(listener func(*model.Config, *model.Config)) string
|
|
||||||
RemoveConfigListener(id string)
|
|
||||||
UpdateConfig(f func(*model.Config))
|
|
||||||
SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// licenseSvc is added to act as a starting point for future integrated products.
|
// licenseSvc is added to act as a starting point for future integrated products.
|
||||||
// It has the same signature and functionality with the license related APIs of the plugin-api.
|
// It has the same signature and functionality with the license related APIs of the plugin-api.
|
||||||
type licenseSvc interface {
|
type licenseSvc interface {
|
||||||
@@ -49,7 +40,7 @@ type namer interface {
|
|||||||
// Channels contains all channels related state.
|
// Channels contains all channels related state.
|
||||||
type Channels struct {
|
type Channels struct {
|
||||||
srv *Server
|
srv *Server
|
||||||
cfgSvc configSvc
|
cfgSvc product.ConfigService
|
||||||
filestore filestore.FileBackend
|
filestore filestore.FileBackend
|
||||||
licenseSvc licenseSvc
|
licenseSvc licenseSvc
|
||||||
routerSvc *routerService
|
routerSvc *routerService
|
||||||
@@ -135,7 +126,7 @@ func NewChannels(s *Server, services map[ServiceKey]interface{}) (*Channels, err
|
|||||||
switch svcKey {
|
switch svcKey {
|
||||||
// Keep adding more services here
|
// Keep adding more services here
|
||||||
case ConfigKey:
|
case ConfigKey:
|
||||||
cfgSvc, ok := svc.(configSvc)
|
cfgSvc, ok := svc.(product.ConfigService)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Config service did not satisfy ConfigSvc interface")
|
return nil, errors.New("Config service did not satisfy ConfigSvc interface")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ package app
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Product interface {
|
type Product interface {
|
||||||
@@ -80,18 +78,3 @@ func (s *Server) initializeProducts(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type logWrapper struct {
|
|
||||||
srv *Server
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *logWrapper) LogError(productID, msg string, keyValuePairs ...interface{}) {
|
|
||||||
s.srv.Log.Error(msg, mlog.String("product_id", productID), mlog.Map("key-value pairs", keyValuePairs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *logWrapper) LogWarn(productID, msg string, keyValuePairs ...interface{}) {
|
|
||||||
s.srv.Log.Warn(msg, mlog.String("product_id", productID), mlog.Map("key-value pairs", keyValuePairs))
|
|
||||||
}
|
|
||||||
func (s *logWrapper) LogDebug(productID, msg string, keyValuePairs ...interface{}) {
|
|
||||||
s.srv.Log.Debug(msg, mlog.String("product_id", productID), mlog.Map("key-value pairs", keyValuePairs))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -399,9 +399,7 @@ func NewServer(options ...Option) (*Server, error) {
|
|||||||
FilestoreKey: s.filestore,
|
FilestoreKey: s.filestore,
|
||||||
ClusterKey: s.clusterWrapper,
|
ClusterKey: s.clusterWrapper,
|
||||||
UserKey: New(ServerConnector(s.Channels())),
|
UserKey: New(ServerConnector(s.Channels())),
|
||||||
LogKey: &logWrapper{
|
LogKey: s.GetLogger(),
|
||||||
srv: s,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 8: Initialize products.
|
// Step 8: Initialize products.
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ var BuildDate string
|
|||||||
var BuildHash string
|
var BuildHash string
|
||||||
var BuildHashEnterprise string
|
var BuildHashEnterprise string
|
||||||
var BuildEnterpriseReady string
|
var BuildEnterpriseReady string
|
||||||
|
var BuildHashBoards string
|
||||||
|
var BuildBoards string
|
||||||
var versionsWithoutHotFixes []string
|
var versionsWithoutHotFixes []string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -4,10 +4,14 @@
|
|||||||
package product
|
package product
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v6/app/request"
|
"github.com/mattermost/mattermost-server/v6/app/request"
|
||||||
"github.com/mattermost/mattermost-server/v6/model"
|
"github.com/mattermost/mattermost-server/v6/model"
|
||||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/shared/filestore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RouterService enables registering the product router to the server. After registering the
|
// RouterService enables registering the product router to the server. After registering the
|
||||||
@@ -95,11 +99,13 @@ type BotService interface {
|
|||||||
EnsureBot(ctx *request.Context, productID string, bot *model.Bot) (string, error)
|
EnsureBot(ctx *request.Context, productID string, bot *model.Bot) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogService shall be registered via app.LogKey service key.
|
// ConfigService shall be registered via app.ConfigKey service key.
|
||||||
type LogService interface {
|
type ConfigService interface {
|
||||||
LogError(productID, msg string, keyValuePairs ...interface{})
|
Config() *model.Config
|
||||||
LogWarn(productID, msg string, keyValuePairs ...interface{})
|
AddConfigListener(listener func(*model.Config, *model.Config)) string
|
||||||
LogDebug(productID, msg string, keyValuePairs ...interface{})
|
RemoveConfigListener(id string)
|
||||||
|
UpdateConfig(f func(*model.Config))
|
||||||
|
SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hooks is an interim solution for enabling plugin hooks on the multi-product architecture. After the
|
// Hooks is an interim solution for enabling plugin hooks on the multi-product architecture. After the
|
||||||
@@ -116,3 +122,15 @@ type Hooks interface {
|
|||||||
type HooksService interface {
|
type HooksService interface {
|
||||||
RegisterHooks(productID string, hooks Hooks) error
|
RegisterHooks(productID string, hooks Hooks) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilestoreService is the API for accessing the file store.
|
||||||
|
//
|
||||||
|
// The service shall be registered via app.FilestoreKey service key.
|
||||||
|
type FilestoreService interface {
|
||||||
|
Reader(path string) (filestore.ReadCloseSeeker, error)
|
||||||
|
FileExists(path string) (bool, error)
|
||||||
|
CopyFile(oldPath, newPath string) error
|
||||||
|
MoveFile(oldPath, newPath string) error
|
||||||
|
WriteFile(fr io.Reader, path string) (int64, error)
|
||||||
|
RemoveFile(path string) error
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,11 +3,18 @@
|
|||||||
if [[ ! -f "go.work" ]] ;
|
if [[ ! -f "go.work" ]] ;
|
||||||
then
|
then
|
||||||
echo "Creating a go.work file"
|
echo "Creating a go.work file"
|
||||||
cat >go.work <<EOL
|
|
||||||
go 1.18
|
|
||||||
|
|
||||||
use ./
|
txt="go 1.18\n\nuse ./\n"
|
||||||
|
|
||||||
use ../enterprise
|
if [ "$BUILD_ENTERPRISE_READY" == "true" ]
|
||||||
EOL
|
then
|
||||||
fi
|
txt="${txt}use ../enterprise\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$BUILD_BOARDS" == "true" ]
|
||||||
|
then
|
||||||
|
txt="${txt}use ../focalboard/server\nuse ../focalboard/mattermost-plugin\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "$txt" > "go.work"
|
||||||
|
fi
|
||||||
@@ -37,6 +37,7 @@ type LoggerIFace interface {
|
|||||||
Critical(string, ...Field)
|
Critical(string, ...Field)
|
||||||
Log(Level, string, ...Field)
|
Log(Level, string, ...Field)
|
||||||
LogM([]Level, string, ...Field)
|
LogM([]Level, string, ...Field)
|
||||||
|
With(fields ...Field) *Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type and function aliases from Logr to limit the spread of dependencies.
|
// Type and function aliases from Logr to limit the spread of dependencies.
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user