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

feat(kuma-cp) Proxy Template modifications #883

Merged
merged 26 commits into from
Jul 17, 2020

Conversation

jakubdyszkiewicz
Copy link
Contributor

@jakubdyszkiewicz jakubdyszkiewicz commented Jul 3, 2020

Summary

This PR introduces long-awaited modifications to Envoy config generated by Kuma 🎉

For now implemented parts are:

  • Clusters
  • Listener
  • Network filter
  • HTTP filter

TODO

  • Implement VirtualHost and Route
  • consider adding modifications to EDS (ClusterLoadAssignment/Endpoints. I missed it in the proposal. If not in this PR, create an issue.
  • Docs (I think we should include a lot of examples with explanation, just like in proposal)

Documentation

kumahq/kuma-website#238

@jakubdyszkiewicz
Copy link
Contributor Author

type: ProxyTemplate
name: pt-1
mesh: default
conf:
  imports:
  - default-proxy
  modifications:
  - cluster:
      operation: patch
      value: |
        connectTimeout: "10s"
  - cluster:
      operation: add
      value: |
        connectTimeout: "5s"
        loadAssignment:
          clusterName: test:cluster
          endpoints:
          - lbEndpoints:
            - endpoint:
                address:
                  socketAddress:
                    address: 192.168.0.1
                    portValue: 8080
        name: test-cluster
        type: STATIC
  - cluster:
      operation: remove
      match:
        name: kuma:envoy:admin
  - networkFilter:
      operation: remove
      match:
        direction: outbound
  - networkFilter:
      operation: addFirst
      match:
        direction: outbound
      value: |
        name: envoy.filters.network.direct_response
        typedConfig:
          '@type': type.googleapis.com/envoy.config.filter.network.direct_response.v2.Config
          response:
            inlineString: |
              HTTP/1.1 200 OK
              content-length: 13

              Hello, World!

Some cool example for testing (patch all cluster timeouts, add a new one, remove existing. Remove all network filters on outbound and add static response)

Nikolay Nikolaev added 5 commits July 12, 2020 11:23
Signed-off-by: Nikolay Nikolaev <nikolay.nikolaev@konghq.com>
Signed-off-by: Nikolay Nikolaev <nikolay.nikolaev@konghq.com>
Signed-off-by: Nikolay Nikolaev <nikolay.nikolaev@konghq.com>
@jakubdyszkiewicz jakubdyszkiewicz marked this pull request as ready for review July 15, 2020 11:06
@jakubdyszkiewicz jakubdyszkiewicz requested a review from a team as a code owner July 15, 2020 11:06
Copy link
Contributor

@nickolaev nickolaev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much straight forward. I like it a lot!

Makefile Outdated
echo '// Import all Envoy packages so protobuf are registered and are ready to used in functions such as MarshalAny.' >> imports.go
echo '// This file is autogenerated. run "make generate/envoy-imports" to regenerate it after go-control-plane upgrade' >> imports.go
echo 'import (' >> imports.go
go list github.com/envoyproxy/go-control-plane/... | grep "github.com/envoyproxy/go-control-plane/envoy/" | awk '{printf "\t_ \"%s\"\n", $$1}' >> imports.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we run into versioning issues here? Is there a way to pin what we test and support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know it uses version from go.mod. The only problem here is that after upgrade go-control-plane we need to rerun it, because there might be new packages.

Makefile Outdated Show resolved Hide resolved
// Network Filter modification
NetworkFilter networkFilter = 3;
// HTTP Filter modification
HttpFilter httpFilter = 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this all? I look here https://www.envoyproxy.io/docs/envoy/latest/api-v2/api, and there are more entities.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are only a couple of fundamental Envoy resources:

  • Cluster - it's here
  • Listener - it's here
  • ClusterLoadAssignment - there might be a use case of adding extra endpoint, but I don't want to implement it for now. I think I'll open an issue for this and maybe someone from the community will pick this up.
  • RouteConfiguration - I want to add it in a separate PR
  • Secret - I don't think there will be a use case for this
  • Runtime - again, no "popular" use case for now

You can see a lot of entities that are embedded in fundamental types. We added modifications for filters because it needs a special treatment (add in proper order). Having a "framework" for modifications we can later easily add other extension points if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK that makes sense.

"github.com/Kong/kuma/pkg/core"
"github.com/Kong/kuma/pkg/core/runtime/component"
"github.com/kumahq/kuma/pkg/core"
"github.com/kumahq/kuma/pkg/core/runtime/component"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fixed in master :)

// Resource represents a generic xDS resource with name and version.
type Resource struct {
Name string
Version string
Origin string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why removing the version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version is useless here. We don't use it anyways, we override version anyways (see SnapshotAutoVersioner)

@jakubdyszkiewicz
Copy link
Contributor Author

Docs kumahq/kuma-website#238

}
case mesh_proto.OpRemove:
default:
verr.AddViolation("operation", fmt.Sprintf("invalid operation. Available operations: %q, %q, %q, %q, %q", mesh_proto.OpAddFirst, mesh_proto.OpAddLast, mesh_proto.OpAddBefore, mesh_proto.OpAddAfter, mesh_proto.OpPatch))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You missed mesh_proto.OpRemove here

}
case mesh_proto.OpRemove:
default:
verr.AddViolation("operation", fmt.Sprintf("invalid operation. Available operations: %q, %q, %q, %q, %q", mesh_proto.OpAddFirst, mesh_proto.OpAddLast, mesh_proto.OpAddBefore, mesh_proto.OpAddAfter, mesh_proto.OpPatch))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

func ValidateResourceYAML(msg proto.Message, resYAML string) error {
json, err := yaml.YAMLToJSON([]byte(resYAML))
if err != nil {
json = []byte(resYAML)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it legal? If err is not nil then resYAML already json for sure?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, probably you imply that it will fail further

if s.typeToNamesIndex[typeName] == nil {
s.typeToNamesIndex[typeName] = map[string]bool{}
for typ, resources := range set.typeToNamesIndex {
if s.typeToNamesIndex[typ] == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can reuse s.Add here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, not exactly. I'd have to do s.Add(set.List()...) which creates a lot of lists etc.

msgTypeName := strings.ReplaceAll(dst.TypeUrl, googleApis, "") // TypeURL in Any contains type.googleapis.com/ prefix, but in Proto registry it does not have this prefix.
msgType := proto.MessageType(msgTypeName).Elem()

dstMsg := reflect.New(msgType).Interface().(proto.Message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is ptypes.UnmarshalAny(any *any.Any, pb proto.Message) error, so you don't need to use reflect

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but then what do you pass as pb proto.Message? We don't know what is the type.
I tried to experiment with DynamicAny

func MergeAnys(dst *any.Any, src *any.Any) (*any.Any, error) {
	if src == nil {
		return dst, nil
	}
	if dst == nil {
		return src, nil
	}
	if src.TypeUrl != dst.TypeUrl {
		return nil, errors.Errorf("type URL of dst %q is different than src %q", dst.TypeUrl, src.TypeUrl)
	}

	dstMsg := &ptypes.DynamicAny{}
	if err := ptypes.UnmarshalAny(dst, dstMsg); err != nil {
		return nil, err
	}

	srcMsg := &ptypes.DynamicAny{}
	if err := ptypes.UnmarshalAny(src, srcMsg); err != nil {
		return nil, err
	}

	proto.Merge(dstMsg, srcMsg)
	any, err := MarshalAnyDeterministic(dstMsg)
	if err != nil {
		return nil, err
	}
	any.TypeUrl = src.TypeUrl
	return any, nil
}

but there is a problem with merging on DynamicAny objects

@jakubdyszkiewicz jakubdyszkiewicz merged commit 9e7fa3b into master Jul 17, 2020
@jakubdyszkiewicz jakubdyszkiewicz deleted the feat/proxy-template-modifications branch July 17, 2020 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants