Skip to content

Commit

Permalink
Add 'verify' command
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Schneider committed Sep 2, 2021
1 parent 3a466c2 commit e6bed97
Show file tree
Hide file tree
Showing 17 changed files with 87 additions and 27 deletions.
2 changes: 2 additions & 0 deletions command/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ func NewCommand(ctx context.Context, cmd string) Cmd {
return NewHelp(ctx)
case "version":
return NewVersion()
case "verify":
return NewVerify()
default:
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions command/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ Couper usage:
Available commands:
help Usage for given command.
run Start the server with given configuration file.
verify Verify the syntax of the given configuration file.
version Print the current version and build information.
Examples:
couper run
couper run -f couper.hcl
couper run -watch -log-format json -log-pretty -p 3000
couper verify -f couper.hcl
`)
}

Expand Down
4 changes: 2 additions & 2 deletions command/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func TestNewRun(t *testing.T) {
return
}

couperFile, fileErr := configload.LoadFile(filepath.Join(wd, "testdata/settings", tt.file))
couperFile, fileErr := configload.LoadFile(filepath.Join(wd, "testdata/settings", tt.file), false)
helper.Must(fileErr)

if len(tt.envs) > 0 {
Expand Down Expand Up @@ -161,7 +161,7 @@ func TestAcceptForwarded(t *testing.T) {
return
}

couperFile, fileErr := configload.LoadFile(filepath.Join(wd, "testdata/settings", tt.file))
couperFile, fileErr := configload.LoadFile(filepath.Join(wd, "testdata/settings", tt.file), false)
helper.Must(fileErr)

if len(tt.envs) > 0 {
Expand Down
41 changes: 41 additions & 0 deletions command/verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package command

import (
"fmt"

"github.com/avenga/couper/config"
"github.com/avenga/couper/config/configload"
"github.com/hashicorp/hcl/v2"
"github.com/sirupsen/logrus"
)

var _ Cmd = &Verify{}

type Verify struct{}

func NewVerify() *Verify {
return &Verify{}
}

func (v Verify) Execute(args Args, _ *config.Couper, logger *logrus.Entry) error {
if len(args) != 1 {
v.Usage()
logger.Error(fmt.Errorf("invalid number of arguments given"))
return fmt.Errorf("")
}

_, err := configload.LoadFile(args[0], true)
if diags, ok := err.(hcl.Diagnostics); ok {
for _, err := range diags {
logger.Error(err)
}

return fmt.Errorf("")
}

return err
}

func (v Verify) Usage() {
println("Usage of verify:\n verify [-f <file>] Verify the syntax of the given configuration file.")
}
12 changes: 6 additions & 6 deletions config/configload/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func SetWorkingDirectory(configFile string) (string, error) {
return os.Getwd()
}

func LoadFile(filePath string) (*config.Couper, error) {
func LoadFile(filePath string, verifyOnly bool) (*config.Couper, error) {
_, err := SetWorkingDirectory(filePath)
if err != nil {
return nil, err
Expand All @@ -69,20 +69,20 @@ func LoadFile(filePath string) (*config.Couper, error) {
return nil, fmt.Errorf("failed to load configuration: %w", err)
}

return LoadBytes(src, filename)
return LoadBytes(src, filename, verifyOnly)
}

func LoadBytes(src []byte, filename string) (*config.Couper, error) {
func LoadBytes(src []byte, filename string, verifyOnly bool) (*config.Couper, error) {
hclBody, diags := parser.Load(src, filename)
if diags.HasErrors() {
return nil, diags
}

return LoadConfig(hclBody, src, filename)
return LoadConfig(hclBody, src, filename, verifyOnly)
}

func LoadConfig(body hcl.Body, src []byte, filename string) (*config.Couper, error) {
if diags := ValidateConfigSchema(body, &config.Couper{}); diags.HasErrors() {
func LoadConfig(body hcl.Body, src []byte, filename string, verifyOnly bool) (*config.Couper, error) {
if diags := ValidateConfigSchema(body, &config.Couper{}); diags.HasErrors() || verifyOnly {
return nil, diags
}

Expand Down
4 changes: 2 additions & 2 deletions eval/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func TestDefaultEnvVariables(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl")
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl", false)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -239,7 +239,7 @@ func TestCouperVariables(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl")
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl", false)
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 3 additions & 3 deletions eval/lib/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ BShcGHZl9nzWDtEZzgdX7cbG5nRUo1+whzBQdYoQmg==

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl")
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl", false)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -414,7 +414,7 @@ func TestJwtSignDynamic(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
helper := test.New(t)

cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl")
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl", false)
helper.Must(err)

claims, err := stdlib.JSONDecode(cty.StringVal(tt.claims))
Expand Down Expand Up @@ -589,7 +589,7 @@ func TestJwtSignError(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(st *testing.T) {
helper := test.New(st)
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl")
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl", false)
helper.Must(err)
claims, err := stdlib.JSONDecode(cty.StringVal(tt.claims))
helper.Must(err)
Expand Down
4 changes: 2 additions & 2 deletions eval/lib/merge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
func TestMerge(t *testing.T) {
helper := test.New(t)

cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl")
cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl", false)
helper.Must(err)

tests := []struct {
Expand Down Expand Up @@ -281,7 +281,7 @@ func TestMerge(t *testing.T) {
func TestMergeErrors(t *testing.T) {
helper := test.New(t)

cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl")
cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl", false)
helper.Must(err)

tests := []struct {
Expand Down
2 changes: 1 addition & 1 deletion eval/lib/saml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func Test_SamlSsoUrl(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(st *testing.T) {
h := test.New(st)
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl")
cf, err := configload.LoadBytes([]byte(tt.hcl), "couper.hcl", false)
if err != nil {
if tt.wantErr {
return
Expand Down
2 changes: 1 addition & 1 deletion eval/lib/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
func TestUnixtime(t *testing.T) {
helper := test.New(t)

cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl")
cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl", false)
helper.Must(err)

hclContext := cf.Context.Value(request.ContextType).(*eval.Context).HCLContext()
Expand Down
2 changes: 1 addition & 1 deletion eval/lib/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
func TestUrlEncode(t *testing.T) {
helper := test.New(t)

cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl")
cf, err := configload.LoadBytes([]byte(`server "test" {}`), "couper.hcl", false)
helper.Must(err)

hclContext := cf.Context.Value(request.ContextType).(*eval.Context).HCLContext()
Expand Down
2 changes: 1 addition & 1 deletion fuzz/server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ settings {
}
`, upstream.Addr(), upstream.Addr())

configFile, err := configload.LoadBytes([]byte(configFileContent), "fuzz_http.hcl")
configFile, err := configload.LoadBytes([]byte(configFileContent), "fuzz_http.hcl", false)
if err != nil {
panic(err)
}
Expand Down
16 changes: 13 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func realmain(arguments []string) int {
cmd := args[0]
args = args[1:]

if cmd != "run" { // global options are not required atm, fast exit.
if cmd != "run" && cmd != "verify" { // global options are not required atm, fast exit.
err := command.NewCommand(ctx, cmd).Execute(args, nil, nil)
if err != nil {
set.Usage()
Expand All @@ -88,7 +88,17 @@ func realmain(arguments []string) int {
}
env.Decode(&flags)

confFile, err := configload.LoadFile(flags.FilePath)
if cmd == "verify" {
log := newLogger(flags.LogFormat, flags.LogLevel, flags.LogPretty)

err := command.NewCommand(ctx, cmd).Execute(command.Args{flags.FilePath}, nil, log)
if err != nil {
return 1
}
return 0
}

confFile, err := configload.LoadFile(flags.FilePath, false)
if err != nil {
newLogger(flags.LogFormat, flags.LogLevel, flags.LogPretty).WithError(err).Error()
return 1
Expand Down Expand Up @@ -168,7 +178,7 @@ func realmain(arguments []string) int {
errRetries = 0 // reset
logger.Info("reloading couper configuration")

cf, reloadErr := configload.LoadFile(confFile.Filename) // we are at wd, just filename
cf, reloadErr := configload.LoadFile(confFile.Filename, false) // we are at wd, just filename
if reloadErr != nil {
logger.WithError(reloadErr).Error("reload failed")
time.Sleep(flags.FileWatchRetryDelay)
Expand Down
4 changes: 4 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func Test_realmain(t *testing.T) {
wantLog string
want int
}{
{"verify -f w/o file", []string{"couper", "verify", "-f", base + "/10_couper.hcl"}, nil, `10_couper.hcl:1,8-9: Missing name for server; All server blocks must have 1 labels (name).`, 1},

This comment has been minimized.

Copy link
@johakoch

johakoch Sep 9, 2021

Collaborator

Why "w/o file"? The file is given as base + "/10_couper.hcl".

{"common log format & info log level /wo file", []string{"couper", "run"}, nil, `level=error msg="failed to load configuration: open couper.hcl: no such file or directory" build=dev`, 1},
{"common log format via env /wo file", []string{"couper", "run", "-log-format", "json"}, []string{"COUPER_LOG_FORMAT=common"}, `level=error msg="failed to load configuration: open couper.hcl: no such file or directory" build=dev`, 1},
{"info log level via env /wo file", []string{"couper", "run", "-log-level", "debug"}, []string{"COUPER_LOG_LEVEL=info"}, `level=error msg="failed to load configuration: open couper.hcl: no such file or directory" build=dev`, 1},
Expand Down Expand Up @@ -53,6 +54,9 @@ func Test_realmain(t *testing.T) {
}
env.OsEnviron = os.Environ

// e := localHook.LastEntry()

This comment has been minimized.

Copy link
@johakoch

johakoch Sep 9, 2021

Collaborator

Can this be removed?

// t.Errorf("%#v", e.Message)

entry, _ := localHook.LastEntry().String()
//println(entry)
if tt.wantLog != "" && !strings.Contains(entry, tt.wantLog) {
Expand Down
6 changes: 3 additions & 3 deletions server/http_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func teardown() {
testBackend.Close()
}
func newCouper(file string, helper *test.Helper) (func(), *logrustest.Hook) {
couperConfig, err := configload.LoadFile(filepath.Join(testWorkingDir, file))
couperConfig, err := configload.LoadFile(filepath.Join(testWorkingDir, file), false)
helper.Must(err)

return newCouperWithConfig(couperConfig, helper)
Expand Down Expand Up @@ -107,7 +107,7 @@ func newCouperWithTemplate(file string, helper *test.Helper, vars map[string]int
}

func newCouperWithBytes(file []byte, helper *test.Helper) (func(), *logrustest.Hook) {
couperConfig, err := configload.LoadBytes(file, "couper-bytes.hcl")
couperConfig, err := configload.LoadBytes(file, "couper-bytes.hcl", false)
helper.Must(err)

return newCouperWithConfig(couperConfig, helper)
Expand Down Expand Up @@ -2829,7 +2829,7 @@ func TestJWTAccessControl(t *testing.T) {

func TestJWTAccessControlSourceConfig(t *testing.T) {
helper := test.New(t)
couperConfig, err := configload.LoadFile("testdata/integration/config/05_couper.hcl")
couperConfig, err := configload.LoadFile("testdata/integration/config/05_couper.hcl", false)
helper.Must(err)

log, _ := logrustest.NewNullLogger()
Expand Down
4 changes: 2 additions & 2 deletions server/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestHTTPServer_ServeHTTP_Files(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

conf, err := configload.LoadBytes(confBytes.Bytes(), "conf_test.hcl")
conf, err := configload.LoadBytes(confBytes.Bytes(), "conf_test.hcl", false)
helper.Must(err)
conf.Settings.DefaultPort = 0

Expand Down Expand Up @@ -154,7 +154,7 @@ func TestHTTPServer_ServeHTTP_Files2(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

conf, err := configload.LoadBytes(confBytes.Bytes(), "conf_fileserving.hcl")
conf, err := configload.LoadBytes(confBytes.Bytes(), "conf_fileserving.hcl", false)
helper.Must(err)

error404Content := []byte("<html><body><h1>route not found error: My custom error template</h1></body></html>")
Expand Down
1 change: 1 addition & 0 deletions server/testdata/settings/10_couper.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
server {}

0 comments on commit e6bed97

Please sign in to comment.