-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from Anmol1696/anmol/exposer
Anmol/exposer
- Loading branch information
Showing
15 changed files
with
559 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
EXAMPLE = upgrade-testing | ||
EXAMPLE = mesh-security | ||
FILE = custom-values.yaml | ||
|
||
HELM_REPO = shuttle | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"github.com/go-chi/chi" | ||
"github.com/go-chi/chi/middleware" | ||
"github.com/go-chi/render" | ||
"go.uber.org/zap" | ||
"net/http" | ||
"time" | ||
) | ||
|
||
type AppServer struct { | ||
config *Config | ||
logger *zap.Logger | ||
server *http.Server | ||
router http.Handler | ||
} | ||
|
||
func NewAppServer(config *Config) (*AppServer, error) { | ||
log, err := NewLogger(config) | ||
if err != nil { | ||
return nil, err | ||
} | ||
log.Info( | ||
"Starting the service", | ||
zap.String("prog", Prog), | ||
zap.String("version", Version), | ||
zap.Any("config", config), | ||
) | ||
|
||
app := &AppServer{ | ||
config: config, | ||
logger: log, | ||
} | ||
|
||
// Setup routes | ||
router, err := app.Router() | ||
if err != nil { | ||
log.Error("Error setting up routes", zap.Error(err)) | ||
return nil, err | ||
} | ||
app.router = router | ||
|
||
return app, err | ||
} | ||
|
||
func (a *AppServer) Router() (*chi.Mux, error) { | ||
router := chi.NewRouter() | ||
router.MethodNotAllowed(MethodNotAllowed) | ||
router.NotFound(NotFound) | ||
|
||
// Set middleware | ||
router.Use(a.panicRecovery) | ||
router.Use(render.SetContentType(render.ContentTypeJSON)) | ||
|
||
// Setup routes | ||
router.Get("/node_id", a.GetNodeID) | ||
router.Get("/pub_key", a.GetPubKey) | ||
router.Get("/genesis", a.GetGenesisFile) | ||
router.Get("/keys", a.GetKeysFile) | ||
|
||
return router, nil | ||
} | ||
|
||
func (a *AppServer) loggingMiddleware(next http.Handler) http.Handler { | ||
fn := func(w http.ResponseWriter, r *http.Request) { | ||
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) | ||
start := time.Now() | ||
defer func() { | ||
a.logger.Info("client request", | ||
zap.Duration("latency", time.Since(start)), | ||
zap.Int("status", ww.Status()), | ||
zap.Int("bytes", ww.BytesWritten()), | ||
zap.String("client_ip", r.RemoteAddr), | ||
zap.String("method", r.Method), | ||
zap.String("path", r.URL.Path), | ||
zap.String("request-id", middleware.GetReqID(r.Context()))) | ||
}() | ||
|
||
next.ServeHTTP(ww, r) | ||
} | ||
return http.HandlerFunc(fn) | ||
} | ||
|
||
func (a *AppServer) panicRecovery(next http.Handler) http.Handler { | ||
fn := func(w http.ResponseWriter, r *http.Request) { | ||
defer func() { | ||
if rc := recover(); rc != nil { | ||
err, ok := rc.(error) | ||
if !ok { | ||
err = fmt.Errorf("panic: %v", rc) | ||
} | ||
a.logger.Error("panic error", | ||
zap.String("request-id", middleware.GetReqID(r.Context())), | ||
zap.Error(err)) | ||
|
||
render.Render(w, r, ErrInternalServer) | ||
return | ||
} | ||
}() | ||
next.ServeHTTP(w, r) | ||
} | ||
return http.HandlerFunc(fn) | ||
} | ||
|
||
func (a *AppServer) Run() error { | ||
a.logger.Info("App starting", zap.Any("Config", a.config)) | ||
|
||
// Setup server | ||
server := &http.Server{ | ||
Addr: a.config.Addr, | ||
Handler: a.router, | ||
} | ||
a.server = server | ||
|
||
// Start http server as long-running go routine | ||
go func() { | ||
if err := server.ListenAndServe(); err != nil { | ||
a.logger.Error("failed to start the App HTTP server", zap.Error(err)) | ||
} | ||
}() | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
|
||
"github.com/urfave/cli" | ||
"go.uber.org/zap" | ||
) | ||
|
||
func NewDefaultConfig() *Config { | ||
return &Config{ | ||
Addr: ":8081", | ||
GenesisFile: "", | ||
MnemonicFile: "", | ||
StatusURL: "http://0.0.0.0:26657/status", | ||
} | ||
} | ||
|
||
type Config struct { | ||
// Addr is the interface and port to bind the HTTP service on | ||
Addr string `name:"addr" json:"addr" env:"ADDR" usage:"IP address and port to listen on"` | ||
// GenesisFile is full path to the genesis file | ||
GenesisFile string `name:"genesis-file" json:"genesis_file" env:"GENESIS_FILE" usage:"Path of genesis file"` | ||
// MnemonicFile is full path to the keys file | ||
MnemonicFile string `name:"mnemonic-file" json:"mnemonic_file" env:"MNEMONIC_FILE" usage:"Path of mnemonic file"` | ||
// StatusURL is used to fetch status info from blockchain node | ||
StatusURL string `name:"status-url" json:"status_url" env:"STATUS_URL" usage:"URL to fetch chain status"` | ||
// Verbose switches on debug logging | ||
Verbose bool `name:"verbose" json:"verbose" usage:"switch on debug / verbose logging"` | ||
// OnlyFatalLog set log level as fatal to ignore logs | ||
OnlyFatalLog bool `name:"only-fatal-log" json:"only-fatal-log" usage:"used while running test"` | ||
} | ||
|
||
func GetCommandLineOptions() []cli.Flag { | ||
defaults := NewDefaultConfig() | ||
var flags []cli.Flag | ||
count := reflect.TypeOf(Config{}).NumField() | ||
for i := 0; i < count; i++ { | ||
field := reflect.TypeOf(Config{}).Field(i) | ||
usage, found := field.Tag.Lookup("usage") | ||
if !found { | ||
continue | ||
} | ||
envName := field.Tag.Get("env") | ||
if envName != "" { | ||
envName = envPrefix + envName | ||
} | ||
optName := field.Tag.Get("name") | ||
|
||
switch t := field.Type; t.Kind() { | ||
case reflect.Bool: | ||
dv := reflect.ValueOf(defaults).Elem().FieldByName(field.Name).Bool() | ||
msg := fmt.Sprintf("%s (default: %t)", usage, dv) | ||
flags = append(flags, cli.BoolTFlag{ | ||
Name: optName, | ||
Usage: msg, | ||
EnvVar: envName, | ||
}) | ||
case reflect.String: | ||
defaultValue := reflect.ValueOf(defaults).Elem().FieldByName(field.Name).String() | ||
flags = append(flags, cli.StringFlag{ | ||
Name: optName, | ||
Usage: usage, | ||
EnvVar: envName, | ||
Value: defaultValue, | ||
}) | ||
} | ||
} | ||
|
||
return flags | ||
} | ||
|
||
func ParseCLIOptions(cx *cli.Context, config *Config) (err error) { | ||
// iterate the Config and grab command line options via reflection | ||
count := reflect.TypeOf(config).Elem().NumField() | ||
for i := 0; i < count; i++ { | ||
field := reflect.TypeOf(config).Elem().Field(i) | ||
name := field.Tag.Get("name") | ||
|
||
if cx.IsSet(name) { | ||
switch field.Type.Kind() { | ||
case reflect.Bool: | ||
reflect.ValueOf(config).Elem().FieldByName(field.Name).SetBool(cx.Bool(name)) | ||
case reflect.String: | ||
reflect.ValueOf(config).Elem().FieldByName(field.Name).SetString(cx.String(name)) | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func NewLogger(config *Config) (*zap.Logger, error) { | ||
c := zap.NewProductionConfig() | ||
c.DisableCaller = true | ||
// c.Encoding = "console" | ||
|
||
if config.Verbose { | ||
c.DisableCaller = false | ||
c.Development = true | ||
c.DisableStacktrace = true // Disable stack trace for development | ||
c.Level = zap.NewAtomicLevelAt(zap.DebugLevel) | ||
} | ||
|
||
if config.OnlyFatalLog { | ||
c.Level = zap.NewAtomicLevelAt(zap.FatalLevel) | ||
} | ||
|
||
log, err := c.Build() | ||
if err != nil { | ||
return nil, err | ||
} | ||
zap.ReplaceGlobals(log) // Set zap global logger | ||
return log, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package main | ||
|
||
var ( | ||
Version = "v0" | ||
RequestIdCtxKey = &contextKey{"RequestId"} | ||
) | ||
|
||
const ( | ||
Prog = "exposer" | ||
Description = "is a sidecar for running cosmos chain nodes for debugging" | ||
envPrefix = "EXPOSER_" | ||
) | ||
|
||
// copied and modified from net/http/http.go | ||
// contextKey is a value for use with context.WithValue. It's used as | ||
// a pointer, so it fits in an interface{} without allocation. | ||
type contextKey struct { | ||
name string | ||
} | ||
|
||
func (k *contextKey) String() string { return Prog + " context value " + k.name } |
Oops, something went wrong.