Merge branch 'master' into no-additional-init

This commit is contained in:
A.Unger
2021-07-02 13:25:30 +02:00
662 changed files with 43303 additions and 29596 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"github.com/owncloud/ocis/web/pkg/config"
)
//go:generate go run github.com/UnnoTed/fileb0x embed.yml
//go:generate make -C ../.. embed.yml
// assets gets initialized by New and provides the handler.
type assets struct {
+124 -66
View File
File diff suppressed because one or more lines are too long
+34 -8
View File
@@ -1,36 +1,34 @@
package command
import (
"context"
"os"
"strings"
"github.com/owncloud/ocis/ocis-pkg/sync"
"github.com/micro/cli/v2"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/web/pkg/config"
"github.com/owncloud/ocis/web/pkg/flagset"
"github.com/owncloud/ocis/web/pkg/version"
"github.com/spf13/viper"
"github.com/thejerf/suture/v4"
)
// Execute is the entry point for the web command.
func Execute() error {
cfg := config.New()
func Execute(cfg *config.Config) error {
app := &cli.App{
Name: "web",
Version: version.String,
Usage: "Serve ownCloud Web for oCIS",
Compiled: version.Compiled(),
Authors: []*cli.Author{
{
Name: "ownCloud GmbH",
Email: "support@owncloud.com",
},
},
Flags: flagset.RootWithConfig(cfg),
Commands: []*cli.Command{
Server(cfg),
Health(cfg),
@@ -57,11 +55,14 @@ func NewLogger(cfg *config.Config) log.Logger {
log.Level(cfg.Log.Level),
log.Pretty(cfg.Log.Pretty),
log.Color(cfg.Log.Color),
log.File(cfg.Log.File),
)
}
// ParseConfig loads proxy configuration from Viper known paths.
func ParseConfig(c *cli.Context, cfg *config.Config) error {
sync.ParsingViperConfig.Lock()
defer sync.ParsingViperConfig.Unlock()
logger := NewLogger(cfg)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
@@ -102,3 +103,28 @@ func ParseConfig(c *cli.Context, cfg *config.Config) error {
return nil
}
// SutureService allows for the web command to be embedded and supervised by a suture supervisor tree.
type SutureService struct {
cfg *config.Config
}
// NewSutureService creates a new web.SutureService
func NewSutureService(cfg *ociscfg.Config) suture.Service {
if cfg.Mode == 0 {
cfg.Web.Supervised = true
}
cfg.Web.Log.File = cfg.Log.File
return SutureService{
cfg: cfg.Web,
}
}
func (s SutureService) Serve(ctx context.Context) error {
s.cfg.Context = ctx
if err := Execute(s.cfg); err != nil {
return err
}
return nil
}
+30 -140
View File
@@ -4,25 +4,17 @@ import (
"context"
"encoding/json"
"io/ioutil"
"os"
"os/signal"
"strings"
"time"
"contrib.go.opencensus.io/exporter/jaeger"
"contrib.go.opencensus.io/exporter/ocagent"
"contrib.go.opencensus.io/exporter/zipkin"
"github.com/micro/cli/v2"
"github.com/oklog/run"
openzipkin "github.com/openzipkin/zipkin-go"
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
"github.com/owncloud/ocis/ocis-pkg/sync"
"github.com/owncloud/ocis/web/pkg/config"
"github.com/owncloud/ocis/web/pkg/flagset"
"github.com/owncloud/ocis/web/pkg/metrics"
"github.com/owncloud/ocis/web/pkg/server/debug"
"github.com/owncloud/ocis/web/pkg/server/http"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
"github.com/owncloud/ocis/web/pkg/tracing"
)
// Server is the entrypoint for the server command.
@@ -30,112 +22,33 @@ func Server(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "server",
Usage: "Start integrated server",
Flags: flagset.ServerWithConfig(cfg),
Before: func(c *cli.Context) error {
Flags: append(flagset.ServerWithConfig(cfg), flagset.RootWithConfig(cfg)...),
Before: func(ctx *cli.Context) error {
logger := NewLogger(cfg)
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimRight(cfg.HTTP.Root, "/")
}
cfg.Web.Config.Apps = c.StringSlice("web-config-app")
cfg.Web.Config.Apps = ctx.StringSlice("web-config-app")
if err := ParseConfig(c, cfg); err != nil {
return err
if !cfg.Supervised {
if err := ParseConfig(ctx, cfg); err != nil {
return err
}
}
logger.Debug().Str("service", "web").Msg("ignoring config file parsing when running supervised")
// build well known openid-configuration endpoint if it is not set
if cfg.Web.Config.OpenIDConnect.MetadataURL == "" {
cfg.Web.Config.OpenIDConnect.MetadataURL = strings.TrimRight(cfg.Web.Config.OpenIDConnect.Authority, "/") + "/.well-known/openid-configuration"
}
return nil
},
Action: func(c *cli.Context) error {
logger := NewLogger(cfg)
if cfg.Tracing.Enabled {
switch t := cfg.Tracing.Type; t {
case "agent":
exporter, err := ocagent.NewExporter(
ocagent.WithReconnectionPeriod(5*time.Second),
ocagent.WithAddress(cfg.Tracing.Endpoint),
ocagent.WithServiceName(cfg.Tracing.Service),
)
if err != nil {
logger.Error().
Err(err).
Str("endpoint", cfg.Tracing.Endpoint).
Str("collector", cfg.Tracing.Collector).
Msg("Failed to create agent tracing")
return err
}
trace.RegisterExporter(exporter)
view.RegisterExporter(exporter)
case "jaeger":
exporter, err := jaeger.NewExporter(
jaeger.Options{
AgentEndpoint: cfg.Tracing.Endpoint,
CollectorEndpoint: cfg.Tracing.Collector,
Process: jaeger.Process{
ServiceName: cfg.Tracing.Service,
},
},
)
if err != nil {
logger.Error().
Err(err).
Str("endpoint", cfg.Tracing.Endpoint).
Str("collector", cfg.Tracing.Collector).
Msg("Failed to create jaeger tracing")
return err
}
trace.RegisterExporter(exporter)
case "zipkin":
endpoint, err := openzipkin.NewEndpoint(
cfg.Tracing.Service,
cfg.Tracing.Endpoint,
)
if err != nil {
logger.Error().
Err(err).
Str("endpoint", cfg.Tracing.Endpoint).
Str("collector", cfg.Tracing.Collector).
Msg("Failed to create zipkin tracing")
return err
}
exporter := zipkin.NewExporter(
zipkinhttp.NewReporter(
cfg.Tracing.Collector,
),
endpoint,
)
trace.RegisterExporter(exporter)
default:
logger.Warn().
Str("type", t).
Msg("Unknown tracing backend")
}
trace.ApplyConfig(
trace.Config{
DefaultSampler: trace.AlwaysSample(),
},
)
} else {
logger.Debug().
Msg("Tracing is not enabled")
if err := tracing.Configure(cfg, logger); err != nil {
return err
}
// actually read the contents of the config file and override defaults
@@ -145,13 +58,21 @@ func Server(cfg *config.Config) *cli.Command {
logger.Err(err).Msg("error opening config file")
return err
}
json.Unmarshal(contents, &cfg.Web.Config)
if err := json.Unmarshal(contents, &cfg.Web.Config); err != nil {
logger.Fatal().Err(err).Msg("error unmarshalling config file")
return err
}
}
var (
gr = run.Group{}
ctx, cancel = context.WithCancel(context.Background())
metrics = metrics.New()
ctx, cancel = func() (context.Context, context.CancelFunc) {
if cfg.Context == nil {
return context.WithCancel(context.Background())
}
return context.WithCancel(cfg.Context)
}()
metrics = metrics.New()
)
defer cancel()
@@ -163,7 +84,6 @@ func Server(cfg *config.Config) *cli.Command {
http.Namespace(cfg.HTTP.Namespace),
http.Config(cfg),
http.Metrics(metrics),
http.Flags(flagset.RootWithConfig(config.New())),
)
if err != nil {
@@ -201,48 +121,18 @@ func Server(cfg *config.Config) *cli.Command {
)
if err != nil {
logger.Info().
Err(err).
Str("transport", "debug").
Msg("Failed to initialize server")
logger.Info().Err(err).Str("transport", "debug").Msg("Failed to initialize server")
return err
}
gr.Add(func() error {
return server.ListenAndServe()
}, func(_ error) {
ctx, timeout := context.WithTimeout(ctx, 5*time.Second)
defer timeout()
defer cancel()
if err := server.Shutdown(ctx); err != nil {
logger.Info().
Err(err).
Str("transport", "debug").
Msg("Failed to shutdown server")
} else {
logger.Info().
Str("transport", "debug").
Msg("Shutting down server")
}
gr.Add(server.ListenAndServe, func(_ error) {
_ = server.Shutdown(ctx)
cancel()
})
}
{
stop := make(chan os.Signal, 1)
gr.Add(func() error {
signal.Notify(stop, os.Interrupt)
<-stop
return nil
}, func(err error) {
close(stop)
cancel()
})
if !cfg.Supervised {
sync.Trap(&gr, cancel)
}
return gr.Run()
+6
View File
@@ -1,10 +1,13 @@
package config
import "context"
// Log defines the available logging configuration.
type Log struct {
Level string
Pretty bool
Color bool
File string
}
// Debug defines the available debug configuration.
@@ -93,6 +96,9 @@ type Config struct {
Asset Asset
OIDC OIDC
Web Web
Context context.Context
Supervised bool
}
// New initializes a new configuration with or without defaults.
+35 -27
View File
@@ -2,6 +2,7 @@ package flagset
import (
"github.com/micro/cli/v2"
"github.com/owncloud/ocis/ocis-pkg/flags"
"github.com/owncloud/ocis/web/pkg/config"
)
@@ -10,23 +11,20 @@ func RootWithConfig(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "log-level",
Value: "info",
Usage: "Set logging level",
EnvVars: []string{"WEB_LOG_LEVEL"},
EnvVars: []string{"WEB_LOG_LEVEL", "OCIS_LOG_LEVEL"},
Destination: &cfg.Log.Level,
},
&cli.BoolFlag{
Name: "log-pretty",
Value: true,
Usage: "Enable pretty logging",
EnvVars: []string{"WEB_LOG_PRETTY"},
EnvVars: []string{"WEB_LOG_PRETTY", "OCIS_LOG_PRETTY"},
Destination: &cfg.Log.Pretty,
},
&cli.BoolFlag{
Name: "log-color",
Value: true,
Usage: "Enable colored logging",
EnvVars: []string{"WEB_LOG_COLOR"},
EnvVars: []string{"WEB_LOG_COLOR", "OCIS_LOG_COLOR"},
Destination: &cfg.Log.Color,
},
}
@@ -37,7 +35,7 @@ func HealthWithConfig(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "debug-addr",
Value: "0.0.0.0:9104",
Value: flags.OverrideDefaultString(cfg.Debug.Addr, "0.0.0.0:9104"),
Usage: "Address to debug endpoint",
EnvVars: []string{"WEB_DEBUG_ADDR"},
Destination: &cfg.Debug.Addr,
@@ -48,6 +46,12 @@ func HealthWithConfig(cfg *config.Config) []cli.Flag {
// ServerWithConfig applies cfg to the root flagset
func ServerWithConfig(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "log-file",
Usage: "Enable log to file",
EnvVars: []string{"WEB_LOG_FILE", "OCIS_LOG_FILE"},
Destination: &cfg.Log.File,
},
&cli.StringFlag{
Name: "config-file",
Value: "",
@@ -63,42 +67,42 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
},
&cli.StringFlag{
Name: "tracing-type",
Value: "jaeger",
Value: flags.OverrideDefaultString(cfg.Tracing.Type, "jaeger"),
Usage: "Tracing backend type",
EnvVars: []string{"WEB_TRACING_TYPE"},
Destination: &cfg.Tracing.Type,
},
&cli.StringFlag{
Name: "tracing-endpoint",
Value: "",
Value: flags.OverrideDefaultString(cfg.Tracing.Endpoint, ""),
Usage: "Endpoint for the agent",
EnvVars: []string{"WEB_TRACING_ENDPOINT"},
Destination: &cfg.Tracing.Endpoint,
},
&cli.StringFlag{
Name: "tracing-collector",
Value: "",
Value: flags.OverrideDefaultString(cfg.Tracing.Collector, ""),
Usage: "Endpoint for the collector",
EnvVars: []string{"WEB_TRACING_COLLECTOR"},
Destination: &cfg.Tracing.Collector,
},
&cli.StringFlag{
Name: "tracing-service",
Value: "web",
Value: flags.OverrideDefaultString(cfg.Tracing.Service, "web"),
Usage: "Service name for tracing",
EnvVars: []string{"WEB_TRACING_SERVICE"},
Destination: &cfg.Tracing.Service,
},
&cli.StringFlag{
Name: "debug-addr",
Value: "0.0.0.0:9104",
Value: flags.OverrideDefaultString(cfg.Debug.Addr, "0.0.0.0:9104"),
Usage: "Address to bind debug server",
EnvVars: []string{"WEB_DEBUG_ADDR"},
Destination: &cfg.Debug.Addr,
},
&cli.StringFlag{
Name: "debug-token",
Value: "",
Value: flags.OverrideDefaultString(cfg.Debug.Token, ""),
Usage: "Token to grant metrics access",
EnvVars: []string{"WEB_DEBUG_TOKEN"},
Destination: &cfg.Debug.Token,
@@ -117,63 +121,63 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
},
&cli.StringFlag{
Name: "http-addr",
Value: "0.0.0.0:9100",
Value: flags.OverrideDefaultString(cfg.HTTP.Addr, "0.0.0.0:9100"),
Usage: "Address to bind http server",
EnvVars: []string{"WEB_HTTP_ADDR"},
Destination: &cfg.HTTP.Addr,
},
&cli.StringFlag{
Name: "http-root",
Value: "/",
Value: flags.OverrideDefaultString(cfg.HTTP.Root, "/"),
Usage: "Root path of http server",
EnvVars: []string{"WEB_HTTP_ROOT"},
Destination: &cfg.HTTP.Root,
},
&cli.StringFlag{
Name: "http-namespace",
Value: "com.owncloud.web",
Value: flags.OverrideDefaultString(cfg.HTTP.Namespace, "com.owncloud.web"),
Usage: "Set the base namespace for the http namespace",
EnvVars: []string{"WEB_NAMESPACE"},
Destination: &cfg.HTTP.Namespace,
},
&cli.IntFlag{
Name: "http-cache-ttl",
Value: 604800, // 7 days
Value: flags.OverrideDefaultInt(cfg.HTTP.CacheTTL, 604800), // 7 days
Usage: "Set the static assets caching duration in seconds",
EnvVars: []string{"WEB_CACHE_TTL"},
Destination: &cfg.HTTP.CacheTTL,
},
&cli.StringFlag{
Name: "asset-path",
Value: "",
Value: flags.OverrideDefaultString(cfg.Asset.Path, ""),
Usage: "Path to custom assets",
EnvVars: []string{"WEB_ASSET_PATH"},
Destination: &cfg.Asset.Path,
},
&cli.StringFlag{
Name: "web-config",
Value: "",
Value: flags.OverrideDefaultString(cfg.Web.Path, ""),
Usage: "Path to web config",
EnvVars: []string{"WEB_UI_CONFIG"},
Destination: &cfg.Web.Path,
},
&cli.StringFlag{
Name: "web-config-server",
Value: "https://localhost:9200",
Value: flags.OverrideDefaultString(cfg.Web.Config.Server, "https://localhost:9200"),
Usage: "Server URL",
EnvVars: []string{"WEB_UI_CONFIG_SERVER", "OCIS_URL"}, // WEB_UI_CONFIG_SERVER takes precedence over OCIS_URL
Destination: &cfg.Web.Config.Server,
},
&cli.StringFlag{
Name: "web-config-theme",
Value: "owncloud",
Value: flags.OverrideDefaultString(cfg.Web.Config.Theme, "owncloud"),
Usage: "Theme",
EnvVars: []string{"WEB_UI_CONFIG_THEME"},
Destination: &cfg.Web.Config.Theme,
},
&cli.StringFlag{
Name: "web-config-version",
Value: "0.1.0",
Value: flags.OverrideDefaultString(cfg.Web.Config.Version, "0.1.0"),
Usage: "Version",
EnvVars: []string{"WEB_UI_CONFIG_VERSION"},
Destination: &cfg.Web.Config.Version,
@@ -186,38 +190,42 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
},
&cli.StringFlag{
Name: "oidc-metadata-url",
Value: "",
Value: flags.OverrideDefaultString(cfg.Web.Config.OpenIDConnect.MetadataURL, ""),
Usage: "OpenID Connect metadata URL, defaults to <WEB_OIDC_AUTHORITY>/.well-known/openid-configuration",
EnvVars: []string{"WEB_OIDC_METADATA_URL"},
Destination: &cfg.Web.Config.OpenIDConnect.MetadataURL,
},
&cli.StringFlag{
Name: "oidc-authority",
Value: "https://localhost:9200",
Value: flags.OverrideDefaultString(cfg.Web.Config.OpenIDConnect.Authority, "https://localhost:9200"),
Usage: "OpenID Connect authority", // TODO rename to Issuer
EnvVars: []string{"WEB_OIDC_AUTHORITY", "OCIS_URL"}, // WEB_OIDC_AUTHORITY takes precedence over OCIS_URL
Destination: &cfg.Web.Config.OpenIDConnect.Authority,
},
&cli.StringFlag{
Name: "oidc-client-id",
Value: "web",
Value: flags.OverrideDefaultString(cfg.Web.Config.OpenIDConnect.ClientID, "web"),
Usage: "OpenID Connect client ID",
EnvVars: []string{"WEB_OIDC_CLIENT_ID"},
Destination: &cfg.Web.Config.OpenIDConnect.ClientID,
},
&cli.StringFlag{
Name: "oidc-response-type",
Value: "code",
Value: flags.OverrideDefaultString(cfg.Web.Config.OpenIDConnect.ResponseType, "code"),
Usage: "OpenID Connect response type",
EnvVars: []string{"WEB_OIDC_RESPONSE_TYPE"},
Destination: &cfg.Web.Config.OpenIDConnect.ResponseType,
},
&cli.StringFlag{
Name: "oidc-scope",
Value: "openid profile email",
Value: flags.OverrideDefaultString(cfg.Web.Config.OpenIDConnect.Scope, "openid profile email"),
Usage: "OpenID Connect scope",
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",
},
}
}
+6 -2
View File
@@ -34,7 +34,9 @@ func health(cfg *config.Config) func(http.ResponseWriter, *http.Request) {
// TODO(tboerger): check if services are up and running
io.WriteString(w, http.StatusText(http.StatusOK))
if _, err := io.WriteString(w, http.StatusText(http.StatusOK)); err != nil {
panic(err)
}
}
}
@@ -46,6 +48,8 @@ func ready(cfg *config.Config) func(http.ResponseWriter, *http.Request) {
// TODO(tboerger): check if services are up and running
io.WriteString(w, http.StatusText(http.StatusOK))
if _, err := io.WriteString(w, http.StatusText(http.StatusOK)); err != nil {
panic(err)
}
}
}
+3 -1
View File
@@ -49,7 +49,9 @@ func Server(opts ...Option) (http.Service, error) {
handle = svc.NewTracing(handle)
}
micro.RegisterHandler(service.Server(), handle)
if err := micro.RegisterHandler(service.Server(), handle); err != nil {
return http.Service{}, err
}
return service, nil
}
+4 -1
View File
@@ -121,7 +121,9 @@ func (p Web) Config(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(payload)
if _, err := w.Write(payload); err != nil {
p.logger.Error().Err(err).Msg("could not write config response")
}
}
// Static simply serves all static files.
@@ -175,6 +177,7 @@ func (p Web) Static(ttl int) http.HandlerFunc {
w.Header().Set("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
w.Header().Set("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
w.Header().Set("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
w.Header().Set("SameSite", "Strict")
static.ServeHTTP(w, r)
}
+90
View File
@@ -0,0 +1,90 @@
package tracing
import (
"time"
"contrib.go.opencensus.io/exporter/jaeger"
"contrib.go.opencensus.io/exporter/ocagent"
"contrib.go.opencensus.io/exporter/zipkin"
openzipkin "github.com/openzipkin/zipkin-go"
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/web/pkg/config"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
)
func Configure(cfg *config.Config, logger log.Logger) error {
if cfg.Tracing.Enabled {
switch t := cfg.Tracing.Type; t {
case "agent":
exporter, err := ocagent.NewExporter(
ocagent.WithReconnectionPeriod(5*time.Second),
ocagent.WithAddress(cfg.Tracing.Endpoint),
ocagent.WithServiceName(cfg.Tracing.Service),
)
if err != nil {
logger.Error().
Err(err).
Str("endpoint", cfg.Tracing.Endpoint).
Str("collector", cfg.Tracing.Collector).
Msg("Failed to create agent tracing")
return err
}
trace.RegisterExporter(exporter)
view.RegisterExporter(exporter)
case "jaeger":
exporter, err := jaeger.NewExporter(
jaeger.Options{
AgentEndpoint: cfg.Tracing.Endpoint,
CollectorEndpoint: cfg.Tracing.Collector,
Process: jaeger.Process{
ServiceName: cfg.Tracing.Service,
},
},
)
if err != nil {
logger.Error().
Err(err).
Str("endpoint", cfg.Tracing.Endpoint).
Str("collector", cfg.Tracing.Collector).
Msg("Failed to create jaeger tracing")
return err
}
trace.RegisterExporter(exporter)
case "zipkin":
endpoint, err := openzipkin.NewEndpoint(
cfg.Tracing.Service,
cfg.Tracing.Endpoint,
)
if err != nil {
logger.Error().
Err(err).
Str("endpoint", cfg.Tracing.Endpoint).
Str("collector", cfg.Tracing.Collector).
Msg("Failed to create zipkin tracing")
return err
}
exporter := zipkin.NewExporter(
zipkinhttp.NewReporter(
cfg.Tracing.Collector,
),
endpoint,
)
trace.RegisterExporter(exporter)
default:
logger.Warn().
Str("type", t).
Msg("Unknown tracing backend")
}
trace.ApplyConfig(
trace.Config{
DefaultSampler: trace.AlwaysSample(),
},
)
} else {
logger.Debug().
Msg("Tracing is not enabled")
}
return nil
}