diff --git a/accounts/pkg/flagset/flagset.go b/accounts/pkg/flagset/flagset.go index 9542d75c32..028e0cd5b3 100644 --- a/accounts/pkg/flagset/flagset.go +++ b/accounts/pkg/flagset/flagset.go @@ -28,6 +28,10 @@ func RootWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"ACCOUNTS_LOG_COLOR", "OCIS_LOG_COLOR"}, Destination: &cfg.Log.Color, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode", + }, } } @@ -235,6 +239,10 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"ACCOUNTS_GID_INDEX_UPPER_BOUND"}, Destination: &cfg.Index.GID.Upper, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode", + }, } } diff --git a/changelog/unreleased/extensions-cherrypick.md b/changelog/unreleased/extensions-cherrypick.md new file mode 100644 index 0000000000..6fa4f89d9b --- /dev/null +++ b/changelog/unreleased/extensions-cherrypick.md @@ -0,0 +1,9 @@ +Enhancement: Runtime support for cherry picking extensions + +Support for running certain extensions supervised via cli flags. Example usage: + +``` +> ocis server --extensions="proxy, idp, storage-metadata, accounts" +``` + +https://github.com/owncloud/ocis/pull/2229 diff --git a/glauth/pkg/flagset/flagset.go b/glauth/pkg/flagset/flagset.go index d3bc91a002..29ef1069a7 100644 --- a/glauth/pkg/flagset/flagset.go +++ b/glauth/pkg/flagset/flagset.go @@ -291,5 +291,9 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"GLAUTH_FALLBACK_USE_GRAPHAPI"}, Destination: &cfg.Fallback.UseGraphAPI, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/graph-explorer/pkg/flagset/flagset.go b/graph-explorer/pkg/flagset/flagset.go index baa5723f2e..54ca8b446f 100644 --- a/graph-explorer/pkg/flagset/flagset.go +++ b/graph-explorer/pkg/flagset/flagset.go @@ -154,5 +154,9 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"GRAPH_EXPLORER_GRAPH_URL"}, Destination: &cfg.GraphExplorer.GraphURL, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/graph/pkg/flagset/flagset.go b/graph/pkg/flagset/flagset.go index 8b96cbf372..495eb7b6b5 100644 --- a/graph/pkg/flagset/flagset.go +++ b/graph/pkg/flagset/flagset.go @@ -216,5 +216,9 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"STORAGE_WEBDAV_NAMESPACE"}, Destination: &cfg.WebdavNamespace, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/idp/pkg/flagset/flagset.go b/idp/pkg/flagset/flagset.go index 9b4c154377..aa41ee52a1 100644 --- a/idp/pkg/flagset/flagset.go +++ b/idp/pkg/flagset/flagset.go @@ -417,7 +417,10 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"IDP_REFRESH_TOKEN_EXPIRATION"}, Destination: &cfg.IDP.RefreshTokenDurationSeconds, Value: flags.OverrideDefaultUint64(cfg.IDP.RefreshTokenDurationSeconds, 60*60*24*365*3), // 1 year - + }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", }, } } diff --git a/ocis-pkg/config/config.go b/ocis-pkg/config/config.go index b6a652e609..5c392471a1 100644 --- a/ocis-pkg/config/config.go +++ b/ocis-pkg/config/config.go @@ -70,8 +70,9 @@ type Mode int // Runtime configures the oCIS runtime when running in supervised mode. type Runtime struct { - Port string - Host string + Port string + Host string + Extensions string } // Config combines all available configuration parts. diff --git a/ocis/pkg/flagset/flagset.go b/ocis/pkg/flagset/flagset.go index 1267d64753..e9dd545349 100644 --- a/ocis/pkg/flagset/flagset.go +++ b/ocis/pkg/flagset/flagset.go @@ -162,5 +162,12 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"OCIS_GRPC_ADDR"}, Destination: &cfg.GRPC.Addr, }, + &cli.StringFlag{ + Name: "extensions", + Aliases: []string{"e"}, + Usage: "Run specific extensions during supervised mode", + EnvVars: []string{"OCIS_RUN_EXTENSIONS"}, + Destination: &cfg.Runtime.Extensions, + }, } } diff --git a/ocis/pkg/runtime/service/service.go b/ocis/pkg/runtime/service/service.go index 268d7473fd..3e9767e3a3 100644 --- a/ocis/pkg/runtime/service/service.go +++ b/ocis/pkg/runtime/service/service.go @@ -22,6 +22,7 @@ import ( graphExplorer "github.com/owncloud/ocis/graph-explorer/pkg/command" graph "github.com/owncloud/ocis/graph/pkg/command" idp "github.com/owncloud/ocis/idp/pkg/command" + "github.com/owncloud/ocis/ocis-pkg/config" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/log" ocs "github.com/owncloud/ocis/ocs/pkg/command" @@ -37,11 +38,18 @@ import ( "github.com/thejerf/suture/v4" ) +var ( + // runset keeps track of which extensions to start supervised. + runset []string +) + +type serviceFuncMap map[string]func(*ociscfg.Config) suture.Service + // Service represents a RPC service. type Service struct { Supervisor *suture.Supervisor - ServicesRegistry map[string]func(*ociscfg.Config) suture.Service - Delayed map[string]func(*ociscfg.Config) suture.Service + ServicesRegistry serviceFuncMap + Delayed serviceFuncMap Log log.Logger serviceToken map[string][]suture.ServiceToken @@ -71,8 +79,8 @@ func NewService(options ...Option) (*Service, error) { globalCtx, cancelGlobal := context.WithCancel(context.Background()) s := &Service{ - ServicesRegistry: make(map[string]func(*ociscfg.Config) suture.Service), - Delayed: make(map[string]func(*ociscfg.Config) suture.Service), + ServicesRegistry: make(serviceFuncMap), + Delayed: make(serviceFuncMap), Log: l, serviceToken: make(map[string][]suture.ServiceToken), @@ -180,10 +188,11 @@ func Start(o ...Option) error { } }() - for name := range s.ServicesRegistry { - swap := deepcopy.Copy(s.cfg) - s.serviceToken[name] = append(s.serviceToken[name], s.Supervisor.Add(s.ServicesRegistry[name](swap.(*ociscfg.Config)))) - } + // prepare the set of services to run + s.generateRunSet(s.cfg) + + // schedule services that we are sure don't have interdependencies. + scheduleServiceTokens(s, s.ServicesRegistry) // there are reasons not to do this, but we have race conditions ourselves. Until we resolve them, mind the following disclaimer: // Calling ServeBackground will CORRECTLY start the supervisor running in a new goroutine. It is risky to directly run @@ -195,17 +204,45 @@ func Start(o ...Option) error { // trap will block on halt channel for interruptions. go trap(s, halt) - time.Sleep(1 * time.Second) - // add services with delayed execution. - for name := range s.Delayed { - swap := deepcopy.Copy(s.cfg) - s.serviceToken[name] = append(s.serviceToken[name], s.Supervisor.Add(s.Delayed[name](swap.(*ociscfg.Config)))) - } + time.Sleep(1 * time.Second) + scheduleServiceTokens(s, s.Delayed) return http.Serve(l, nil) } +// scheduleServiceTokens adds service tokens to the service supervisor. +func scheduleServiceTokens(s *Service, funcSet serviceFuncMap) { + for _, name := range runset { + if _, ok := funcSet[name]; !ok { + continue + } + + swap := deepcopy.Copy(s.cfg) + s.serviceToken[name] = append(s.serviceToken[name], s.Supervisor.Add(funcSet[name](swap.(*ociscfg.Config)))) + } +} + +// generateRunSet interprets the cfg.Runtime.Extensions config option to cherry-pick which services to start using +// the runtime. +func (s *Service) generateRunSet(cfg *config.Config) { + if cfg.Runtime.Extensions != "" { + e := strings.Split(strings.ReplaceAll(cfg.Runtime.Extensions, " ", ""), ",") + for i := range e { + runset = append(runset, e[i]) + } + return + } + + for name := range s.ServicesRegistry { + runset = append(runset, name) + } + + for name := range s.Delayed { + runset = append(runset, name) + } +} + // Start indicates the Service Controller to start a new supervised service as an OS thread. func (s *Service) Start(name string, reply *int) error { // RPC calls to a Service object will allow for parsing config. Mind that since the runtime is running on a different diff --git a/ocs/pkg/flagset/flagset.go b/ocs/pkg/flagset/flagset.go index a5e69d7fca..e3ee4e4c24 100644 --- a/ocs/pkg/flagset/flagset.go +++ b/ocs/pkg/flagset/flagset.go @@ -179,6 +179,10 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"OCS_STORAGE_USERS_DRIVER", "STORAGE_USERS_DRIVER"}, Destination: &cfg.StorageUsersDriver, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode", + }, } } diff --git a/onlyoffice/pkg/flagset/flagset.go b/onlyoffice/pkg/flagset/flagset.go index d8a59bd5ae..6517b8dc0b 100644 --- a/onlyoffice/pkg/flagset/flagset.go +++ b/onlyoffice/pkg/flagset/flagset.go @@ -154,5 +154,9 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"ONLYOFFICE_ASSET_PATH"}, Destination: &cfg.Asset.Path, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/proxy/pkg/flagset/flagset.go b/proxy/pkg/flagset/flagset.go index 87ad472d44..b2cbd818e3 100644 --- a/proxy/pkg/flagset/flagset.go +++ b/proxy/pkg/flagset/flagset.go @@ -30,6 +30,10 @@ func RootWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"PROXY_LOG_COLOR", "OCIS_LOG_COLOR"}, Destination: &cfg.Log.Color, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode", + }, } } diff --git a/settings/pkg/flagset/flagset.go b/settings/pkg/flagset/flagset.go index 8aa7a5aab6..8a253abeb5 100644 --- a/settings/pkg/flagset/flagset.go +++ b/settings/pkg/flagset/flagset.go @@ -183,6 +183,10 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"SETTINGS_JWT_SECRET", "OCIS_JWT_SECRET"}, Destination: &cfg.TokenManager.JWTSecret, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/storage/pkg/flagset/storagemetadata.go b/storage/pkg/flagset/storagemetadata.go index fe28e00241..581f7f1f32 100644 --- a/storage/pkg/flagset/storagemetadata.go +++ b/storage/pkg/flagset/storagemetadata.go @@ -106,6 +106,7 @@ func StorageMetadata(cfg *config.Config) []cli.Flag { f = append(f, DriverOwnCloudWithConfig(cfg)...) f = append(f, DriverOCISWithConfig(cfg)...) f = append(f, DriverS3NGWithConfig(cfg)...) + return f } diff --git a/store/pkg/flagset/flagset.go b/store/pkg/flagset/flagset.go index f87f08efc0..578cdf1cca 100644 --- a/store/pkg/flagset/flagset.go +++ b/store/pkg/flagset/flagset.go @@ -140,6 +140,10 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"STORE_DATA_PATH"}, Destination: &cfg.Datapath, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/thumbnails/pkg/flagset/flagset.go b/thumbnails/pkg/flagset/flagset.go index c1c68b8aa1..b020149aa7 100644 --- a/thumbnails/pkg/flagset/flagset.go +++ b/thumbnails/pkg/flagset/flagset.go @@ -169,6 +169,10 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"STORAGE_WEBDAV_NAMESPACE"}, Destination: &cfg.Thumbnail.WebdavNamespace, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode", + }, } } diff --git a/web/pkg/flagset/flagset.go b/web/pkg/flagset/flagset.go index 717663f986..10f6c79f7c 100644 --- a/web/pkg/flagset/flagset.go +++ b/web/pkg/flagset/flagset.go @@ -223,5 +223,9 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"WEB_OIDC_SCOPE"}, Destination: &cfg.Web.Config.OpenIDConnect.Scope, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } } diff --git a/webdav/pkg/flagset/flagset.go b/webdav/pkg/flagset/flagset.go index 0d8a29b955..f77bc528aa 100644 --- a/webdav/pkg/flagset/flagset.go +++ b/webdav/pkg/flagset/flagset.go @@ -142,19 +142,23 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { Destination: &cfg.HTTP.Root, }, &cli.StringFlag{ - Name: "ocis-public-url", - Value: flags.OverrideDefaultString(cfg.OcisPublicURL, "https://127.0.0.1:9200"), - Usage: "The domain under which oCIS is reachable", - EnvVars: []string{"OCIS_PUBLIC_URL", "OCIS_URL"}, + Name: "ocis-public-url", + Value: flags.OverrideDefaultString(cfg.OcisPublicURL, "https://127.0.0.1:9200"), + Usage: "The domain under which oCIS is reachable", + EnvVars: []string{"OCIS_PUBLIC_URL", "OCIS_URL"}, Destination: &cfg.OcisPublicURL, }, &cli.StringFlag{ - Name: "webdav-namespace", - Value: flags.OverrideDefaultString(cfg.WebdavNamespace, "/home"), - Usage: "Namespace prefix for the /webdav endpoint", - EnvVars: []string{"STORAGE_WEBDAV_NAMESPACE"}, + Name: "webdav-namespace", + Value: flags.OverrideDefaultString(cfg.WebdavNamespace, "/home"), + Usage: "Namespace prefix for the /webdav endpoint", + EnvVars: []string{"STORAGE_WEBDAV_NAMESPACE"}, Destination: &cfg.WebdavNamespace, }, + &cli.StringFlag{ + Name: "extensions", + Usage: "Run specific extensions during supervised mode. This flag is set by the runtime", + }, } }