Skip to content

Commit

Permalink
feat(kuma-cp) validate envoy resource
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubdyszkiewicz committed Nov 13, 2019
1 parent 5695181 commit aa58e78
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 26 deletions.
2 changes: 2 additions & 0 deletions pkg/core/resources/apis/mesh/proxytemplate_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ func validateResources(resources []*v1alpha1.ProxyTemplateRawResource) validator
}
if resource.Resource == "" {
verr.AddViolationAt(validators.RootedAt("resources").Index(i).Field("resource"), "cannot be empty")
} else if _, err := template.ResourceFromYaml(resource.Resource); err != nil {
verr.AddViolationAt(validators.RootedAt("resources").Index(i).Field("resource"), err.Error())
}
}
return verr
Expand Down
53 changes: 52 additions & 1 deletion pkg/core/resources/apis/mesh/proxytemplate_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,20 @@ var _ = Describe("ProxyTemplate", func() {
resources:
- name: additional
version: v1
resource: test`
resource: |
'@type': type.googleapis.com/envoy.api.v2.Cluster
connectTimeout: 5s
loadAssignment:
clusterName: localhost:8443
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 127.0.0.1
portValue: 8443
name: localhost:8443
type: STATIC`

proxyTemplate := mesh.ProxyTemplateResource{}

Expand Down Expand Up @@ -126,6 +139,44 @@ var _ = Describe("ProxyTemplate", func() {
- field: 'selectors[0]["service"]'
message: value of tag cannot be empty`,
}),
Entry("validation error from envoy protobuf resource", testCase{
proxyTemplate: `
selectors:
- match:
service: backend
resources:
- name: additional
version: v1
resource: |
'@type': type.googleapis.com/envoy.api.v2.Cluster
loadAssignment:
clusterName: localhost:8443
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 127.0.0.1
portValue: 8443`,
expected: `
violations:
- field: resources[0].resource
message: 'invalid Cluster.Name: value length must be at least 1 bytes'`,
}),
Entry("invalid envoy resource", testCase{
proxyTemplate: `
selectors:
- match:
service: backend
resources:
- name: additional
version: v1
resource: not-envoy-resource`,
expected: `
violations:
- field: resources[0].resource
message: 'json: cannot unmarshal string into Go value of type map[string]*json.RawMessage'`,
}),
)
})
})
27 changes: 2 additions & 25 deletions pkg/xds/generator/proxy_template.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package generator

import (
"bytes"
"fmt"
"sort"
"strings"
Expand All @@ -15,10 +14,6 @@ import (
xds_context "github.com/Kong/kuma/pkg/xds/context"
"github.com/Kong/kuma/pkg/xds/envoy"
"github.com/Kong/kuma/pkg/xds/template"
"github.com/ghodss/yaml"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/ptypes"
any "github.com/golang/protobuf/ptypes/any"
)

type TemplateProxyGenerator struct {
Expand Down Expand Up @@ -51,33 +46,15 @@ type ProxyTemplateRawSource struct {
func (s *ProxyTemplateRawSource) Generate(_ xds_context.Context, proxy *model.Proxy) ([]*Resource, error) {
resources := make([]*Resource, 0, len(s.Resources))
for i, r := range s.Resources {
json, err := yaml.YAMLToJSON([]byte(r.Resource))
res, err := template.ResourceFromYaml(r.Resource)
if err != nil {
json = []byte(r.Resource)
}

var anything any.Any
if err := (&jsonpb.Unmarshaler{}).Unmarshal(bytes.NewReader(json), &anything); err != nil {
return nil, fmt.Errorf("raw.resources[%d]{name=%q}.resource: %s", i, r.Name, err)
}
var dyn ptypes.DynamicAny
if err := ptypes.UnmarshalAny(&anything, &dyn); err != nil {
return nil, fmt.Errorf("raw.resources[%d]{name=%q}.resource: %s", i, r.Name, err)
}
p, ok := dyn.Message.(ResourcePayload)
if !ok {
return nil, fmt.Errorf("raw.resources[%d]{name=%q}.resource: xDS resource doesn't implement all required interfaces", i, r.Name)
}
if v, ok := p.(interface{ Validate() error }); ok {
if err := v.Validate(); err != nil {
return nil, fmt.Errorf("raw.resources[%d]{name=%q}.resource: %s", i, r.Name, err)
}
}

resources = append(resources, &Resource{
Name: r.Name,
Version: r.Version,
Resource: p,
Resource: res,
})
}
return resources, nil
Expand Down
38 changes: 38 additions & 0 deletions pkg/xds/template/raw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package template

import (
"bytes"
"errors"
"github.com/envoyproxy/go-control-plane/pkg/cache"
"github.com/ghodss/yaml"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/any"
)

func ResourceFromYaml(resYaml string) (proto.Message, error) {
json, err := yaml.YAMLToJSON([]byte(resYaml))
if err != nil {
json = []byte(resYaml)
}

var anything any.Any
if err := (&jsonpb.Unmarshaler{}).Unmarshal(bytes.NewReader(json), &anything); err != nil {
return nil, err
}
var dyn ptypes.DynamicAny
if err := ptypes.UnmarshalAny(&anything, &dyn); err != nil {
return nil, err
}
p, ok := dyn.Message.(cache.Resource)
if !ok {
return nil, errors.New("xDS resource doesn't implement all required interfaces")
}
if v, ok := p.(interface{ Validate() error }); ok {
if err := v.Validate(); err != nil {
return nil, err
}
}
return p, nil
}

0 comments on commit aa58e78

Please sign in to comment.