Select Git revision
middleware.go
extension.go 3.78 KiB
package extension
import (
"context"
"io/fs"
"go.uber.org/zap"
"git.perx.ru/perxis/perxis-go"
"git.perx.ru/perxis/perxis-go/pkg/collections"
"git.perx.ru/perxis/perxis-go/pkg/content"
"git.perx.ru/perxis/perxis-go/pkg/errors"
"git.perx.ru/perxis/perxis-go/pkg/schema"
"git.perx.ru/perxis/perxis-go/pkg/setup"
pb "git.perx.ru/perxis/perxis-go/proto/extensions"
)
const (
StateNotInstalled = pb.State_NOT_INSTALLED
StatePending = pb.State_PENDING
StateInstalled = pb.State_INSTALLED
StateInProgress = pb.State_IN_PROGRESS
StateFail = pb.State_FAIL
MetadataKey = "extension"
)
type (
InstallRequest = pb.InstallRequest
CheckRequest = pb.CheckRequest
UninstallRequest = pb.UninstallRequest
ExtensionDescriptor = pb.ExtensionDescriptor
State = pb.State
)
var (
ErrStart = errors.New("start failed")
ErrStop = errors.New("stop failed")
ErrInstall = errors.New("install failed")
ErrUpdate = errors.New("update failed")
ErrCheck = errors.New("check failed")
ErrUninstall = errors.New("uninstall failed")
ErrNotInstalled = errors.New("not installed")
ErrUnknownExtension = errors.New("unknown extension")
)
// Runnable описывает интерфейс сервиса с запуском и остановкой. Вызывается сервером расширений
type Runnable interface {
Start() error
Stop() error
}
// Extension описывает интерфейс расширения Perxis
type Extension interface {
// GetDescriptor возвращает описание расширения
GetDescriptor() *ExtensionDescriptor
// Install вызывается при установке расширения в пространство
Install(ctx context.Context, in *InstallRequest) error
// Check вызывается для проверки состояния расширения
Check(ctx context.Context, in *CheckRequest) error
// Uninstall вызывается для удаления расширения из пространства
Uninstall(ctx context.Context, in *UninstallRequest) error
// Action вызывается для выполнения расширением действия
Action(ctx context.Context, in *ActionRequest) (*ActionResponse, error)
}
func CheckInstalled(ctx context.Context, content *content.Content, spaceID, envID, extension string) (bool, error) {
status, err := NewStorage(content, nil).GetExtension(ctx, spaceID, envID, extension)
if err != nil {
return false, err
}
return status.State == StateInstalled, nil
}
// isSameExtension возвращает true, если значение метаданных для ключа расширения совпадает
func isSameExtension(s1, s2 *schema.Schema) bool {
if s1.Metadata == nil && s2.Metadata == nil {
return true
}
if s1.Metadata == nil || s2.Metadata == nil {
return false
}
return s1.Metadata[MetadataKey] == s2.Metadata[MetadataKey]
}
// UpdateExtensionCollections возвращает опцию для обновления коллекций расширения
func UpdateExtensionCollections() setup.CollectionOption {
return func(e *setup.Collection) {
next := e.UpdateFunc
e.UpdateFunc = func(s *setup.Setup, old, new *collections.Collection) (*collections.Collection, bool) {
if !s.IsForce() && !new.IsView() && !old.IsView() && !isSameExtension(new.Schema, old.Schema) {
s.Logger().Warn("Collection is already exists and not updated", zap.String("ID", new.ID))
return nil, false
}
return next(s, old, new)
}
}
}
// LoadManifest загружает манифест из файла manifest.yaml
func LoadManifest(fsys fs.FS) *ExtensionDescriptor {
return perxis.NewAssets[*ExtensionDescriptor](fsys).MustOneFrom("manifest.yml")
}