Skip to content

Commit

Permalink
feat: move runtime config into cloudruntime package
Browse files Browse the repository at this point in the history
With a specific context key, it becomes easier to mock the runtime in
unit tests.

BREAKING CHANGE: cloudrunner.Service replaced with cloudrunner.Runtime
  • Loading branch information
odsod committed Aug 4, 2021
1 parent 1e03414 commit 5a0e2b3
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 64 deletions.
59 changes: 59 additions & 0 deletions cloudruntime/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cloudruntime

import "context"

// WithConfig adds the provided runtime Config to the current context.
func WithConfig(ctx context.Context, config Config) context.Context {
return context.WithValue(ctx, configContextKey{}, config)
}

// GetConfig gets the runtime Config from the current context.
func GetConfig(ctx context.Context) (Config, bool) {
result, ok := ctx.Value(configContextKey{}).(Config)
return result, ok
}

type configContextKey struct{}

// Config is the runtime config for the service.
type Config struct {
// Port is the port the service is listening on.
Port int `env:"PORT" default:"8080"`
// Service is the name of the service.
Service string `env:"K_SERVICE"`
// Revision of the service, as assigned by a Knative runtime.
Revision string `env:"K_REVISION"`
// Configuration of the service, as assigned by a Knative runtime.
Configuration string `env:"K_CONFIGURATION"`
// ProjectID is the GCP project ID the service is running in.
// In production, defaults to the project where the service is deployed.
ProjectID string `env:"GOOGLE_CLOUD_PROJECT"`
// ServiceAccount is the service account used by the service.
// In production, defaults to the default service account of the running service.
ServiceAccount string
// ServiceVersion is the version of the service.
ServiceVersion string `env:"SERVICE_VERSION"`
}

// Autodetect the runtime config.
func (c *Config) Autodetect() error {
if projectID, ok := ProjectID(); ok {
c.ProjectID = projectID
}
if serviceVersion, ok := ServiceVersion(); ok {
c.ServiceVersion = serviceVersion
}
if serviceAccount, ok := ServiceAccount(); ok {
c.ServiceAccount = serviceAccount
}
if service, ok := Service(); ok {
c.Service = service
}
if revision, ok := Revision(); ok {
c.Revision = revision
}
if configuration, ok := Configuration(); ok {
c.Configuration = configuration
}
return nil
}
2 changes: 1 addition & 1 deletion grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func ListenGRPC(ctx context.Context, grpcServer *grpc.Server) error {
if !ok {
return fmt.Errorf("cloudrunner.ListenGRPC: must be called with a context from cloudrunner.Run")
}
address := fmt.Sprintf(":%d", run.config.Service.Port)
address := fmt.Sprintf(":%d", run.config.Runtime.Port)
listener, err := (&net.ListenConfig{}).Listen(
ctx,
"tcp",
Expand Down
2 changes: 1 addition & 1 deletion httphandler.go → httpserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func NewHTTPServer(ctx context.Context, handler http.Handler, middlewares ...HTT
run.serverMiddleware.HTTPServer,
}
return &http.Server{
Addr: fmt.Sprintf(":%d", run.config.Service.Port),
Addr: fmt.Sprintf(":%d", run.config.Runtime.Port),
Handler: cloudserver.ChainHTTPMiddleware(
handler,
append(defaultMiddlewares, middlewares...)...,
Expand Down
12 changes: 8 additions & 4 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go.einride.tech/cloudrunner/cloudotel"
"go.einride.tech/cloudrunner/cloudprofiler"
"go.einride.tech/cloudrunner/cloudrequestlog"
"go.einride.tech/cloudrunner/cloudruntime"
"go.einride.tech/cloudrunner/cloudserver"
"go.einride.tech/cloudrunner/cloudtrace"
"go.einride.tech/cloudrunner/cloudzap"
Expand All @@ -21,8 +22,8 @@ import (

// runConfig configures the Run entrypoint from environment variables.
type runConfig struct {
// Service contains generic service config.
Service ServiceConfig
// Runtime contains runtime config.
Runtime cloudruntime.Config
// Logger contains logger config.
Logger cloudzap.LoggerConfig
// Profiler contains profiler config.
Expand Down Expand Up @@ -66,14 +67,17 @@ func Run(fn func(context.Context) error, options ...Option) error {
if err := config.Load(); err != nil {
return fmt.Errorf("cloudrunner.Run: %w", err)
}
run.config.Service.loadFromRuntime()
if err := run.config.Runtime.Autodetect(); err != nil {
return fmt.Errorf("cloudrunner.Run: %w", err)
}
if *validate {
return nil
}
run.traceMiddleware.ProjectID = run.config.Service.ProjectID
run.traceMiddleware.ProjectID = run.config.Runtime.ProjectID
run.serverMiddleware.Config = run.config.Server
run.requestLoggerMiddleware.Config = run.config.RequestLogger
ctx = withRunContext(ctx, &run)
ctx = cloudruntime.WithConfig(ctx, run.config.Runtime)
logger, err := cloudzap.NewLogger(run.config.Logger)
if err != nil {
return fmt.Errorf("cloudrunner.Run: %w", err)
Expand Down
16 changes: 16 additions & 0 deletions runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cloudrunner

import (
"context"

"go.einride.tech/cloudrunner/cloudruntime"
)

// Runtime returns the runtime config for the current context.
func Runtime(ctx context.Context) cloudruntime.Config {
config, ok := cloudruntime.GetConfig(ctx)
if !ok {
panic("cloudrunner.Runtime must be called with a context from cloudrunner.Run")
}
return config
}
58 changes: 0 additions & 58 deletions service.go

This file was deleted.

0 comments on commit 5a0e2b3

Please sign in to comment.