Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sequence #405

Merged
merged 68 commits into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
4bf80af
Add config based static req sequence
Dec 3, 2021
346064f
Refactor endpoint produce channel close handling
Dec 3, 2021
e5ef861
add proxies to seq
Dec 3, 2021
8748992
Fix collecting proxy deps
Dec 6, 2021
f8d24c6
Support sequences in parallel
Dec 6, 2021
6c01d1c
Fixup sequence self-ref
Dec 6, 2021
a75e6a4
Fixup test due to endpoint result channel refactoring
Dec 6, 2021
1b9fdb4
tests using same client settings
Dec 6, 2021
47919ab
Fix passed produce context; reduced req ptr value overrides
Dec 6, 2021
aab3d91
Refactor: reduce loop complexity
Dec 6, 2021
99bb9c3
add test for a simple sequence
Dec 6, 2021
d4a840d
more sequence test-cases
Dec 6, 2021
7f4f451
Refactor configload files: ordered methods by context
Dec 7, 2021
dcdda57
remove obsolete methods
Dec 7, 2021
6062991
refactor sequence interface to own file
Dec 7, 2021
964d026
Fixup collecting attr expr for nested blocks
Dec 7, 2021
d98811e
Add sequence cancel and timeout test
Dec 7, 2021
3bcbcab
Fixup missing bufferOptions for sequence context
Dec 8, 2021
5e67d49
Add body value to proxy sequence test
Dec 8, 2021
c296252
fix error type generation, also allow base kinds to be definable
Dec 9, 2021
dea557f
allow error_handler catches for endpoint handler
Dec 9, 2021
ba40d85
Add expected_status attribute to request block; add error handler eve…
Dec 9, 2021
779282d
expected_status should be optional
Dec 9, 2021
a8107e2
fix missing beresp context for error_handler
Dec 9, 2021
f317acd
fixup, check all expected status codes
Dec 9, 2021
2a9c6c6
Fix expstatus since its optional
Dec 9, 2021
3e71a40
Refactor: rename errorTemplate attribute and withErr method
Dec 9, 2021
2a709c4
Refactor: Endpoint handler: error handling
Dec 9, 2021
9e9e1cb
Add expected_status attribute to proxy block
Dec 9, 2021
6a609f4
go fmt
Dec 9, 2021
5a2eed5
fixup revert rename
Dec 9, 2021
80e6494
add sequence error type
Dec 9, 2021
1f536d0
set endpoint log context at the beginning
Dec 10, 2021
427bb62
Fix custom logging for endpoint error_handler
Dec 10, 2021
e23921c
Add new error type documentation
Dec 10, 2021
1d97f7f
Docs: format request and proxy tables
Dec 10, 2021
daafb98
Add expected status attribute docs
Dec 10, 2021
a5078a9
Apply suggestions from code review
Dec 10, 2021
4dfb96a
fixup recursive call
Dec 10, 2021
879f38b
rename newSequences method, plural
Dec 10, 2021
5adafb0
Add unit test for expected_status to producer package
Dec 10, 2021
27b2298
fixup defer
Dec 10, 2021
966638e
rename test
Dec 10, 2021
375f201
Fix possible backend_* variables loss with endpoint error_handler
Dec 10, 2021
6f46ca9
Apply suggestions from code review
Dec 10, 2021
a390de9
moved log level test file to combined log folder
Dec 13, 2021
8480df0
Test custom logs within endpoint error handler
Dec 13, 2021
38ac7ab
fix heading levels
Dec 13, 2021
96f4a03
separate tables for groups of error types
Dec 13, 2021
4e20702
Refactor mergedBody type to own package
Dec 14, 2021
4acba6f
Refactor mustBuffer and fixed nested handling
Dec 14, 2021
dfab600
Add endpoint error_handler test with body variable access
Dec 14, 2021
9f73a3b
Fixup backend roundtrip test; set at least outreq var
Dec 14, 2021
7c269cc
Fix log fields order, ac protected block first
Dec 20, 2021
0ed2d3a
Refactor accessing backend related hcl variables via syncMap
Dec 21, 2021
6cf2897
Refactor several methods to use the hclEvalcontext as argument
Dec 21, 2021
7d88ce5
Fixup handling type assertions, default type value instead of panic
Dec 21, 2021
f702533
Fixup removed default roundtrip name
Dec 21, 2021
947c0de
Fixup backend context handling
Dec 21, 2021
fe71e99
Fix test template format
Dec 21, 2021
818d4ad
parse backend response body just once
Dec 21, 2021
d370864
body naming and access via remain
Dec 21, 2021
fa7d5ac
no format given
Dec 21, 2021
c891778
fixed order of imports
Dec 21, 2021
54fe6e2
Add documentation and changelog entry
Dec 21, 2021
fc36562
toc links
Dec 21, 2021
eac1671
added changelog entry for unexpected_status error type
Dec 21, 2021
36a7a93
Update docs and changelog for unexpected_status
Dec 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ test-coverage:
go test -short -timeout 300s -covermode=count -coverprofile=command.coverage ./command
go test -short -timeout 300s -covermode=count -coverprofile=config.coverage ./config
go test -short -timeout 300s -covermode=count -coverprofile=docs.coverage ./docs
# go test -short -timeout 300s -covermode=count -coverprofile=errors.coverage ./errors
go test -short -timeout 300s -covermode=count -coverprofile=errors.coverage ./errors
go test -short -timeout 300s -covermode=count -coverprofile=eval.coverage ./eval
go test -short -timeout 300s -covermode=count -coverprofile=handler.coverage ./handler
# go test -short -timeout 300s -covermode=count -coverprofile=logging.coverage ./logging
go test -short -timeout 300s -covermode=count -coverprofile=producer.coverage ./handler/producer
go test -short -timeout 300s -covermode=count -coverprofile=logging.coverage ./logging
go test -short -timeout 300s -covermode=count -coverprofile=server.coverage ./server
go test -short -timeout 300s -covermode=count -coverprofile=main.coverage ./

Expand All @@ -41,9 +42,10 @@ test-coverage-show:
go tool cover -html=command.coverage
go tool cover -html=config.coverage
go tool cover -html=docs.coverage
# go tool cover -html=errors.coverage
go tool cover -html=errors.coverage
go tool cover -html=eval.coverage
go tool cover -html=handler.coverage
# go tool cover -html=logging.coverage
go tool cover -html=producer.coverage
go tool cover -html=logging.coverage
go tool cover -html=server.coverage
go tool cover -html=main.coverage
102 changes: 102 additions & 0 deletions config/body/collect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package body

import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)

func CollectAttributes(bodies ...hcl.Body) []*hcl.Attribute {
allAttributes := make([]*hcl.Attribute, 0)

for _, b := range bodies {
switch sb := b.(type) {
case *hclsyntax.Body:
for _, attr := range sb.Attributes {
allAttributes = append(allAttributes, &hcl.Attribute{
Name: attr.Name,
Expr: attr.Expr,
Range: attr.SrcRange,
NameRange: attr.NameRange,
})
}

for _, block := range sb.Blocks {
allAttributes = append(allAttributes, CollectAttributes(block.Body)...)
}
case *Body:
content, _, _ := sb.PartialContent(nil)
for _, attr := range content.Attributes {
allAttributes = append(allAttributes, attr)
}
for _, block := range content.Blocks {
allAttributes = append(allAttributes, CollectAttributes(block.Body)...)
}
case MergedBodies:
// top-level attrs
for _, attrs := range sb.JustAllAttributes() {
for _, attr := range attrs {
allAttributes = append(allAttributes, attr)
}
}

// nested block attrs
for _, mb := range sb {
allAttributes = append(allAttributes, CollectAttributes(mb)...)
}
}
}

return allAttributes
}

func CollectBlockTypes(bodies ...hcl.Body) []string {
unique := make(map[string]struct{})

addUniqueFn := func(types ...string) {
for _, t := range types {
if _, exist := unique[t]; exist {
continue
}
unique[t] = struct{}{}
}
}

for _, b := range bodies {
switch sb := b.(type) {
case *hclsyntax.Body:

for _, block := range sb.Blocks {
nested := append(append([]string{}, block.Type), CollectBlockTypes(block.Body)...)
addUniqueFn(nested...)
}
case *Body:
content, _, _ := sb.PartialContent(nil)
for _, block := range content.Blocks {
nested := append(append([]string{}, block.Type), CollectBlockTypes(block.Body)...)
addUniqueFn(nested...)
}
case MergedBodies:
// nested block
for _, mb := range sb {
nested := append([]string{}, CollectBlockTypes(mb)...)
addUniqueFn(nested...)
}
}
}

var result []string
for u := range unique {
result = append(result, u)
}

return result
}

func CollectExpressions(bodies ...hcl.Body) []hcl.Expression {
allExpressions := make([]hcl.Expression, 0)
for _, attr := range CollectAttributes(bodies...) {
allExpressions = append(allExpressions, attr.Expr)
}

return allExpressions
}
46 changes: 22 additions & 24 deletions config/configload/merged.go → config/body/merged.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// File based on "github.com/hashicorp/hcl/v2/merged.go" except diagnostic errors for duplicates
// since we explicitly want them and apply an override.

package configload
package body

import (
"fmt"

hclbody "github.com/avenga/couper/config/body"
"github.com/hashicorp/hcl/v2"
)

Expand All @@ -15,30 +14,30 @@ var reportDuplicates = false

// MergeBodies is like MergeFiles except it deals directly with bodies, rather
// than with entire files.
func MergeBodies(bodies []hcl.Body) hcl.Body {
func MergeBodies(bodies ...hcl.Body) hcl.Body {
if len(bodies) == 0 {
// Swap out for our singleton empty body, to reduce the number of
// empty slices we have hanging around.
return EmptyBody()
}

// If any of the given bodies are already merged bodies, we'll unpack
// to flatten to a single mergedBodies, since that's conceptually simpler.
// to flatten to a single MergedBodies, since that's conceptually simpler.
// This also, as a side-effect, eliminates any empty bodies, since
// empties are merged bodies with no inner bodies.
var newLen int
var flatten bool
for _, body := range bodies {
if children, merged := body.(mergedBodies); merged {
if children, merged := body.(MergedBodies); merged {
newLen += len(children)
flatten = true
} else {
newLen++
}
}

if !flatten { // not just newLen == len, because we might have mergedBodies with single bodies inside
return mergedBodies(bodies)
if !flatten { // not just newLen == len, because we might have MergedBodies with single bodies inside
return MergedBodies(bodies)
}

if newLen == 0 {
Expand All @@ -48,24 +47,24 @@ func MergeBodies(bodies []hcl.Body) hcl.Body {

newBodies := make([]hcl.Body, 0, newLen)
for _, body := range bodies {
if children, merged := body.(mergedBodies); merged {
if children, merged := body.(MergedBodies); merged {
newBodies = append(newBodies, children...)
} else {
newBodies = append(newBodies, body)
}
}
return mergedBodies(newBodies)
return MergedBodies(newBodies)
}

var emptyBody = mergedBodies([]hcl.Body{})
var emptyBody = MergedBodies([]hcl.Body{})

// EmptyBody returns a body with no content. This body can be used as a
// placeholder when a body is required but no body content is available.
func EmptyBody() hcl.Body {
return emptyBody
}

type mergedBodies []hcl.Body
type MergedBodies []hcl.Body

// Content returns the content produced by applying the given schema to all
// of the merged bodies and merging the result.
Expand All @@ -75,18 +74,18 @@ type mergedBodies []hcl.Body
// with which to return good diagnostics. Applications working with merged
// bodies may wish to mark all attributes as optional and then check for
// required attributes afterwards, to produce better diagnostics.
func (mb mergedBodies) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
func (mb MergedBodies) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
// the returned body will always be empty in this case, because mergedContent
// will only ever call Content on the child bodies.
content, _, diags := mb.mergedContent(schema, false)
return content, diags
}

func (mb mergedBodies) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
func (mb MergedBodies) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
return mb.mergedContent(schema, true)
}

func (mb mergedBodies) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
func (mb MergedBodies) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
attrs := make(map[string]*hcl.Attribute)
var diags hcl.Diagnostics

Expand All @@ -106,7 +105,7 @@ func (mb mergedBodies) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
}

// MissingItemRange returns the first non-empty range if any.
func (mb mergedBodies) MissingItemRange() hcl.Range {
func (mb MergedBodies) MissingItemRange() hcl.Range {
if len(mb) == 0 {
// Nothing useful to return here, so we'll return some garbage.
return hcl.Range{
Expand All @@ -124,7 +123,7 @@ func (mb mergedBodies) MissingItemRange() hcl.Range {
return mb[0].MissingItemRange()
}

func (mb mergedBodies) mergedContent(schema *hcl.BodySchema, partial bool) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
func (mb MergedBodies) mergedContent(schema *hcl.BodySchema, partial bool) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
// We need to produce a new schema with none of the attributes marked as
// required, since _any one_ of our bodies can contribute an attribute value.
// We'll separately check that all required attributes are present at
Expand Down Expand Up @@ -199,13 +198,12 @@ func (mb mergedBodies) mergedContent(schema *hcl.BodySchema, partial bool) (*hcl

diags = append(diags, mergeAttributes(contentAttrs, thisContentAttrs)...)

content.Blocks[idx].Body = MergeBodies([]hcl.Body{
content.Blocks[idx].Body = MergeBodies(
thisContentBlock.Body, // keep child blocks
hclbody.New(&hcl.BodyContent{
New(&hcl.BodyContent{
Attributes: contentAttrs,
MissingItemRange: content.Blocks[idx].DefRange,
}),
})
MissingItemRange: content.Blocks[idx].DefRange}),
)
}
}
}
Expand Down Expand Up @@ -237,18 +235,18 @@ func (mb mergedBodies) mergedContent(schema *hcl.BodySchema, partial bool) (*hcl
}
}

leftoverBody := MergeBodies(mergedLeftovers)
leftoverBody := MergeBodies(mergedLeftovers...)
return content, leftoverBody, diags
}

// JustAllAttributes returns a list of attributes in order. Since these bodies got added as partialContent
// we do not have to supply a scheme or handle the underlying diagnostics.
func (mb mergedBodies) JustAllAttributes() []hcl.Attributes {
func (mb MergedBodies) JustAllAttributes() []hcl.Attributes {
return mb.JustAllAttributesWithName("")
}

// JustAllAttributesWithName behaviour is the same as JustAllAttributes with a filtered slice.
func (mb mergedBodies) JustAllAttributesWithName(name string) []hcl.Attributes {
func (mb MergedBodies) JustAllAttributesWithName(name string) []hcl.Attributes {
var result []hcl.Attributes

for _, body := range mb {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package configload_test
package body_test

import (
"testing"
Expand All @@ -10,7 +10,7 @@ import (
"github.com/zclconf/go-cty/cty"

"github.com/avenga/couper/config"
"github.com/avenga/couper/config/configload"
"github.com/avenga/couper/config/body"
"github.com/avenga/couper/eval"
)

Expand Down Expand Up @@ -83,7 +83,7 @@ block {
}

schema, _ = gohcl.ImpliedBodySchema(bodies.Block[0])
content, _, diags = configload.MergeBodies(hclBodies[:]).PartialContent(schema)
content, _, diags = body.MergeBodies(hclBodies[:]...).PartialContent(schema)
if diags.HasErrors() {
t.Error(diags)
}
Expand Down
Loading