Skip to content

Commit

Permalink
Use embeddable ocdav go micro service (#3397)
Browse files Browse the repository at this point in the history
* allow proxy to route to micro service

Signed-off-by: Jörn Friedrich Dreyer <[email protected]>

* use go micre ocdav service instead of reva frontend

Signed-off-by: Jörn Friedrich Dreyer <[email protected]>

* add missing gateway default config

Signed-off-by: Jörn Friedrich Dreyer <[email protected]>

* update reva branch for testing

Signed-off-by: Jörn Friedrich Dreyer <[email protected]>

* add changelog

Signed-off-by: Jörn Friedrich Dreyer <[email protected]>

* add missing comands

Signed-off-by: Jörn Friedrich Dreyer <[email protected]>

* bump reva version

Signed-off-by: jkoberg <[email protected]>

* tidy

Signed-off-by: jkoberg <[email protected]>

* bump reva again

Signed-off-by: jkoberg <[email protected]>

* a blind mans config change

Signed-off-by: jkoberg <[email protected]>

* add ocdav to must start extensions

Signed-off-by: jkoberg <[email protected]>

* fail when neither backend nor service is set

Signed-off-by: jkoberg <[email protected]>

Co-authored-by: jkoberg <[email protected]>
  • Loading branch information
butonic and kobergj authored Apr 12, 2022
1 parent a61d1ce commit 0e88cb1
Show file tree
Hide file tree
Showing 18 changed files with 310 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -1696,7 +1696,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
"OCIS_STORAGE_READ_ONLY": "false",
# General oCIS config
# OCIS_RUN_EXTENSIONS specifies to start all extensions except glauth, idp and accounts. These are replaced by external services
"OCIS_RUN_EXTENSIONS": "settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,proxy,nats",
"OCIS_RUN_EXTENSIONS": "settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,proxy,nats,ocdav",
"OCIS_LOG_LEVEL": "error",
"OCIS_URL": OCIS_URL,
"PROXY_TLS": "true",
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"ACCOUNTS_DEMO_USERS_AND_GROUPS": "true",
"IDM_CREATE_DEMO_USERS": "true"
// OCIS_RUN_EXTENSIONS allows to start a subset of extensions even in the supervised mode
//"OCIS_RUN_EXTENSIONS": "settings,storage-metadata,glauth,graph,graph-explorer,idp,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,accounts,proxy",
//"OCIS_RUN_EXTENSIONS": "settings,storage-metadata,glauth,graph,graph-explorer,idp,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,accounts,proxy,ocdav",
}
}
]
Expand Down
5 changes: 5 additions & 0 deletions changelog/unreleased/micro-ocdav.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Use embeddable ocdav go micro service

We now use the reva `pgk/micro/ocdav` package that implements a go micro compatible version of the ocdav service.

https://github.com/owncloud/ocis/pull/3397
1 change: 1 addition & 0 deletions changelog/unreleased/update-reva.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Updated reva to version 2.x.x. This update includes:

* TODO

https://github.com/owncloud/ocis/pull/3397
https://github.com/owncloud/ocis/pull/3430
https://github.com/owncloud/ocis/pull/3476
https://github.com/owncloud/ocis/pull/3482
Expand Down
2 changes: 1 addition & 1 deletion docs/extensions/idm/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export STORAGE_LDAP_USERATTRIBUTEFILTER='(&(objectclass=owncloud)({{attr}}={{val
export STORAGE_LDAP_USERFINDFILTER='(&(objectclass=owncloud)(|(uid={{query}}*)(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)(description={{query}}*)))'
export STORAGE_LDAP_USERGROUPFILER='(&(objectclass=groupOfNames)(member={{query}}*))'
export STORAGE_LDAP_GROUPFILTER='(&(objectclass=groupOfNames)(objectclass=owncloud)(ownclouduuid={{.OpaqueId}}*))'
export OCIS_RUN_EXTENSIONS=settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,proxy,idp,nats,idm
export OCIS_RUN_EXTENSIONS=settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,proxy,idp,nats,idm,ocdav
export OCIS_INSECURE=true
bin/ocis server
```
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ require (
github.com/asim/go-micro/plugins/registry/mdns/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/asim/go-micro/plugins/registry/nats/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/asim/go-micro/plugins/server/grpc/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20220317022205-c6d352c83291
github.com/asim/go-micro/plugins/wrapper/breaker/gobreaker/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/asim/go-micro/plugins/wrapper/monitoring/prometheus/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/asim/go-micro/plugins/wrapper/trace/opencensus/v4 v4.0.0-20220118152736-9e0be6c85d75
github.com/blevesearch/bleve/v2 v2.3.2
github.com/coreos/go-oidc/v3 v3.1.0
github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f
github.com/cs3org/reva/v2 v2.0.0-20220411161034-134ed5a0801f
github.com/cs3org/reva/v2 v2.0.0-20220411200520-865ba723f25a
github.com/disintegration/imaging v1.6.2
github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733
github.com/go-chi/chi/v5 v5.0.7
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ github.com/asim/go-micro/plugins/registry/nats/v4 v4.0.0-20220118152736-9e0be6c8
github.com/asim/go-micro/plugins/registry/nats/v4 v4.0.0-20220118152736-9e0be6c85d75/go.mod h1:n4K0361IySJ/hmIfaIg8q2NDNAVDL9DUC6Bh7gS4ihg=
github.com/asim/go-micro/plugins/server/grpc/v4 v4.0.0-20220118152736-9e0be6c85d75 h1:miPpSGbTA6L2hsHccRNxNSXpIYo6YtlTkoi+fvEHJbw=
github.com/asim/go-micro/plugins/server/grpc/v4 v4.0.0-20220118152736-9e0be6c85d75/go.mod h1:uQACKU+/RcWKEMdX6/Ewd+TxCPLIsLPt9ym6++B1X68=
github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20220118152736-9e0be6c85d75 h1:ULuhDMrHjkEkj0dxWS+ZM9MD/9ywFPM7kaoEs4OjhSc=
github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20220118152736-9e0be6c85d75/go.mod h1:LEsuhy4ZF3UGT9VSOoj/ZP0MZt4brlgwJVG7/LAac+I=
github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20220317022205-c6d352c83291 h1:l1l3pUleHu66DNRmaPwfgyXfVXT7UmyzNXD0uQp9SQE=
github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20220317022205-c6d352c83291/go.mod h1:LEsuhy4ZF3UGT9VSOoj/ZP0MZt4brlgwJVG7/LAac+I=
github.com/asim/go-micro/plugins/transport/grpc/v4 v4.0.0-20211019191242-9edc569e68bb h1:rCIGzR4YRddwaWM4pZkbxHIkhFbbuGZOqivnxyKNQz8=
github.com/asim/go-micro/plugins/transport/grpc/v4 v4.0.0-20211019191242-9edc569e68bb/go.mod h1:dzSEAsAqQ4mRaYPJ07KcAt6rIjYUJ9w55UXvnyGx4VE=
github.com/asim/go-micro/plugins/wrapper/breaker/gobreaker/v4 v4.0.0-20220118152736-9e0be6c85d75 h1:8wLNrBKfdRl6uryUFW6qlBZWNeIbPUYKYkwLG9bI58k=
Expand Down Expand Up @@ -335,8 +335,8 @@ github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3p
github.com/crewjam/saml v0.4.6 h1:XCUFPkQSJLvzyl4cW9OvpWUbRf0gE7VUpU8ZnilbeM4=
github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/reva/v2 v2.0.0-20220411161034-134ed5a0801f h1:SNQSbtvhsQ6KvdDJlW536pUMq8RzghQMDCkYYKEFn8c=
github.com/cs3org/reva/v2 v2.0.0-20220411161034-134ed5a0801f/go.mod h1:rE2wCGoiGiUuQ3zj6aD7sZ+BhboLyNsNQ3z3auunWm4=
github.com/cs3org/reva/v2 v2.0.0-20220411200520-865ba723f25a h1:/3filuu6As9ZMznQ3ddShjveqNr0NrjfZynQT3LyTmQ=
github.com/cs3org/reva/v2 v2.0.0-20220411200520-865ba723f25a/go.mod h1:l1dhodFXCp88/Lc0VhzSeaLSQUTn2AdwwkTFtaLCJhk=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
Expand Down
28 changes: 28 additions & 0 deletions ocis/pkg/command/ocdav.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package command

import (
"github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis/pkg/register"
"github.com/owncloud/ocis/storage/pkg/command"
"github.com/urfave/cli/v2"
)

// OCDavCommand is the entrypoint for the ocdav command.
func OCDavCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "ocdav",
Usage: "start ocdav",
Category: "extensions",
Before: func(ctx *cli.Context) error {
return ParseStorageCommon(ctx, cfg)
},
Action: func(c *cli.Context) error {
origCmd := command.OCDav(cfg.Storage)
return handleOriginalAction(c, origCmd)
},
}
}

func init() {
register.AddCommand(OCDavCommand)
}
1 change: 1 addition & 0 deletions ocis/pkg/runtime/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func NewService(options ...Option) (*Service, error) {
s.ServicesRegistry["web"] = web.NewSutureService
s.ServicesRegistry["webdav"] = webdav.NewSutureService
s.ServicesRegistry["storage-frontend"] = storage.NewFrontend
s.ServicesRegistry["ocdav"] = storage.NewOCDav
s.ServicesRegistry["storage-gateway"] = storage.NewGateway
s.ServicesRegistry["storage-userprovider"] = storage.NewUserProvider
s.ServicesRegistry["storage-groupprovider"] = storage.NewGroupProvider
Expand Down
13 changes: 8 additions & 5 deletions proxy/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ type Policy struct {
Routes []Route `yaml:"routes"`
}

// Route define forwarding routes
// Route defines forwarding routes
type Route struct {
Type RouteType `yaml:"type"`
Endpoint string `yaml:"endpoint"`
Backend string `yaml:"backend"`
ApacheVHost bool `yaml:"apache-vhost"`
Type RouteType `yaml:"type"`
Endpoint string `yaml:"endpoint"`
// Backend is a static URL to forward the request to
Backend string `yaml:"backend"`
// Service name to look up in the registry
Service string `yaml:"service"`
ApacheVHost bool `yaml:"apache-vhost"`
}

// RouteType defines the type of a route
Expand Down
16 changes: 10 additions & 6 deletions proxy/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,30 +96,34 @@ func DefaultPolicies() []config.Policy {
},
{
Endpoint: "/remote.php/",
Backend: "http://localhost:9140",
Service: "ocdav",
},
{
Endpoint: "/dav/",
Backend: "http://localhost:9140",
Service: "ocdav",
},
{
Endpoint: "/webdav/",
Backend: "http://localhost:9140",
Service: "ocdav",
},
{
Endpoint: "/status.php",
Backend: "http://localhost:9140",
Service: "ocdav",
},
{
Endpoint: "/index.php/",
Backend: "http://localhost:9140",
Service: "ocdav",
},
{
Endpoint: "/apps/",
Service: "ocdav",
},
{
Endpoint: "/data",
Backend: "http://localhost:9140",
},
{
Endpoint: "/app/",
Endpoint: "/app/", // /app or /apps? ocdav only handles /apps
Backend: "http://localhost:9140",
},
{
Expand Down
33 changes: 31 additions & 2 deletions proxy/pkg/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import (
"time"

chimiddleware "github.com/go-chi/chi/v5/middleware"
"go-micro.dev/v4/selector"

"go.opentelemetry.io/otel/attribute"

"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/registry"
pkgtrace "github.com/owncloud/ocis/ocis-pkg/tracing"
"github.com/owncloud/ocis/proxy/pkg/config"
"github.com/owncloud/ocis/proxy/pkg/proxy/policy"
Expand Down Expand Up @@ -86,6 +88,10 @@ func NewMultiHostReverseProxy(opts ...Option) *MultiHostReverseProxy {
for _, pol := range options.Config.Policies {
for _, route := range pol.Routes {
rp.logger.Debug().Str("fwd: ", route.Endpoint)

if route.Backend == "" && route.Service == "" {
rp.logger.Fatal().Interface("route", route).Msg("neither Backend nor Service is set")
}
uri, err2 := url.Parse(route.Backend)
if err2 != nil {
rp.logger.
Expand All @@ -95,6 +101,7 @@ func NewMultiHostReverseProxy(opts ...Option) *MultiHostReverseProxy {
Msg("malformed url")
}

// here the backend is used as a uri
rp.AddHost(pol.Name, uri, route)
}
}
Expand Down Expand Up @@ -184,9 +191,31 @@ func (p *MultiHostReverseProxy) AddHost(policy string, target *url.URL, rt confi
if p.Directors[policy][routeType] == nil {
p.Directors[policy][routeType] = make(map[string]func(req *http.Request))
}

reg := registry.GetRegistry()
sel := selector.NewSelector(selector.Registry(reg))

p.Directors[policy][routeType][rt.Endpoint] = func(req *http.Request) {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
if rt.Service != "" {
// select next node
next, err := sel.Select(rt.Service)
if err != nil {
fmt.Println(fmt.Errorf("could not select %s service from the registry: %v", rt.Service, err))
return // TODO error? fallback to target.Host & Scheme?
}
node, err := next()
if err != nil {
fmt.Println(fmt.Errorf("could not select next node for service %s: %v", rt.Service, err))
return // TODO error? fallback to target.Host & Scheme?
}
req.URL.Host = node.Address
req.URL.Scheme = node.Metadata["protocol"] // TODO check property exists?

} else {
req.URL.Host = target.Host
req.URL.Scheme = target.Scheme
}

// Apache deployments host addresses need to match on req.Host and req.URL.Host
// see https://stackoverflow.com/questions/34745654/golang-reverseproxy-with-apache2-sni-hostname-error
if rt.ApacheVHost {
Expand Down
8 changes: 0 additions & 8 deletions storage/pkg/command/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,6 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s
"timeout": 86400,
"insecure": true,
},
"ocdav": map[string]interface{}{
"prefix": cfg.Reva.Frontend.OCDavPrefix,
"files_namespace": cfg.Reva.OCDav.DavFilesNamespace,
"webdav_namespace": cfg.Reva.OCDav.WebdavNamespace,
"timeout": 86400,
"insecure": cfg.Reva.Frontend.OCDavInsecure,
"public_url": cfg.Reva.Frontend.PublicURL,
},
"ocs": map[string]interface{}{
"storage_registry_svc": cfg.Reva.Gateway.Endpoint,
"share_prefix": cfg.Reva.Frontend.OCSSharePrefix,
Expand Down
134 changes: 134 additions & 0 deletions storage/pkg/command/ocdav.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package command

import (
"context"
"flag"

"github.com/cs3org/reva/v2/pkg/micro/ocdav"
"github.com/oklog/run"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/sync"
"github.com/owncloud/ocis/storage/pkg/config"
"github.com/owncloud/ocis/storage/pkg/server/debug"
"github.com/owncloud/ocis/storage/pkg/tracing"
"github.com/thejerf/suture/v4"
"github.com/urfave/cli/v2"
)

// OCDav is the entrypoint for the ocdav command.
// TODO move ocdav cmd to a separate service
func OCDav(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "ocdav",
Usage: "start ocdav service",
Before: func(c *cli.Context) error {
if err := loadUserAgent(c, cfg); err != nil {
return err
}
return ParseConfig(c, cfg, "ocdav")
},
Action: func(c *cli.Context) error {
logger := NewLogger(cfg)

tracing.Configure(cfg, logger)

gr := run.Group{}
ctx, cancel := context.WithCancel(context.Background())
//metrics = metrics.New()

defer cancel()

gr.Add(func() error {
s, err := ocdav.Service(
ocdav.Context(ctx),
ocdav.Logger(logger.Logger),
ocdav.Address(cfg.OCDav.Addr),
ocdav.FilesNamespace(cfg.OCDav.FilesNamespace),
ocdav.WebdavNamespace(cfg.OCDav.WebdavNamespace),
ocdav.SharesNamespace(cfg.OCDav.SharesNamespace),
ocdav.Timeout(cfg.OCDav.Timeout),
ocdav.Insecure(cfg.OCDav.Insecure),
ocdav.PublicURL(cfg.OCDav.PublicURL),
ocdav.Prefix(cfg.OCDav.Prefix),
ocdav.GatewaySvc(cfg.OCDav.GatewaySVC),
ocdav.JWTSecret(cfg.OCDav.JWTSecret),
// ocdav.FavoriteManager() // FIXME needs a proper persistence implementation
// ocdav.LockSystem(), // will default to the CS3 lock system
// ocdav.TLSConfig() // tls config for the http server
)
if err != nil {
return err
}

return s.Run()
}, func(err error) {
logger.Info().Err(err).Str("server", c.Command.Name).Msg("Shutting down server")
cancel()
})

{
server, err := debug.Server(
debug.Name(c.Command.Name+"-debug"),
debug.Addr(cfg.OCDav.DebugAddr),
debug.Logger(logger),
debug.Context(ctx),
debug.Config(cfg),
)

if err != nil {
logger.Info().
Err(err).
Str("server", "debug").
Msg("Failed to initialize server")

return err
}

gr.Add(server.ListenAndServe, func(_ error) {
cancel()
})
}

if !cfg.Reva.Frontend.Supervised {
sync.Trap(&gr, cancel)
}

return gr.Run()
},
}
}

// OCDavSutureService allows for the ocdav command to be embedded and supervised by a suture supervisor tree.
type OCDavSutureService struct {
cfg *config.Config
}

// NewOCDav creates a new ocdav.OCDavSutureService
func NewOCDav(cfg *ociscfg.Config) suture.Service {
cfg.Storage.Commons = cfg.Commons
return OCDavSutureService{
cfg: cfg.Storage,
}
}

func (s OCDavSutureService) Serve(ctx context.Context) error {
s.cfg.Reva.Frontend.Context = ctx
f := &flag.FlagSet{}
cmdFlags := OCDav(s.cfg).Flags
for k := range cmdFlags {
if err := cmdFlags[k].Apply(f); err != nil {
return err
}
}
cliCtx := cli.NewContext(nil, f, nil)
if OCDav(s.cfg).Before != nil {
if err := OCDav(s.cfg).Before(cliCtx); err != nil {
return err
}
}
if err := OCDav(s.cfg).Action(cliCtx); err != nil {
return err
}

return nil
}
Loading

0 comments on commit 0e88cb1

Please sign in to comment.