-
Notifications
You must be signed in to change notification settings - Fork 352
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
Add xds-server implementation #176
Conversation
Codecov Report
@@ Coverage Diff @@
## main #176 +/- ##
==========================================
- Coverage 67.57% 61.74% -5.83%
==========================================
Files 20 20
Lines 1659 1814 +155
==========================================
- Hits 1121 1120 -1
- Misses 477 632 +155
- Partials 61 62 +1
Help us with your feedback. Take ten seconds to tell us how you rate us. |
058b360
to
54f2b59
Compare
// xDSTest implements the command. | ||
// This is deliberately verbose and unoptimized, since the purpose | ||
// is just to illustrate how the flow will need to work. | ||
func xDSTest() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the input is fixed, this function would be could be a good candidate for a test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, but in order to test it, we'll need an xDS client, which I'll need to write. That will be a reasonable amount of work, so I wanted to do it in a followup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's roll with the test cmd and create the xds client as part of #177
|
||
} | ||
|
||
func (s *snapshotcache) OnStreamRequest(streamID int64, req *envoy_service_discovery_v3.DiscoveryRequest) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious why SoTW callbacks are implemented, we should just log and return imho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not implementing the full protocol when we can pretty easily makes me uncomfortable - if we do happen to make an error with the Delta callbacks or implementation, the SOTW is a good fallback to have available for operational purposes.
I don't think that not meeting expectations about what variants we support is worth the small saving in development effort.
// Yes, the different ordering in the name is part of the go-control-plane interface. | ||
func (s *snapshotcache) OnDeltaStreamOpen(ctx context.Context, streamID int64, typeURL string) error { | ||
|
||
s.streamIDNodeID[streamID] = "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this tracks rogue streams ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It ensures that the assignment to s.streamIDNodeID[streamID]
in the StreamRequest callback will always succeed, since every stream has StreamOpen called first, then StreamRequest per request received. This could be more defensive though, I'll update.
|
||
// If no snapshot has been generated yet, we can't do anything, so don't mess with this request. | ||
// go-control-plane will respond with an empty response, then send an update when a snapshot is generated. | ||
if s.lastSnapshot == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if s.lastSnapshot == nil { | |
if s.lastSnapshot != nil { | |
err := s.SetSnapshot(context.TODO(), nodeID, s.lastSnapshot); err != nil { | |
... | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, I'm using a Go idiom that basically says "The leftmost side of the code should be the happy path, exceptions should be in if blocks." That way we're not indending most of the rest of the function.
Note that this is a different case to the next one - this one is that no snapshot has been generated by the rest of EG yet, the s.GetSnapshot(nodeID)
call below checks if there's a snapshot with the current Node.
When reviewing the code after @arkodg's comments, I realized that these callbacks need to be concurrent-safe, so I sprinkled some I also realized that requests don't always have to have node ID set, so tidied up the handling there too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks for implementing delta xDS
hoping the xdstest
can be moved to a go test function in a followup PR
@youngnick when you have a moment, please create an issue and xref. |
I created #177 to cover setting up automated testing for the xDS server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nit, and 2 minor suggestions. But IMO mergeable.
internal/log/logrwrapper.go
Outdated
package log | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/go-logr/logr" | ||
) | ||
|
||
// LogrWrapper is a nasty hack for turning the logr.Logger we get from NewLogger() | ||
// into something that go-control-plane can accept. | ||
// It seems pretty silly to take a zap logger, which is levelled, turn it into | ||
// a V-style logr Logger, then turn it back again with this, but here we are. | ||
// TODO(youngnick): Reopen the logging library discussion then do something about this. | ||
type LogrWrapper struct { | ||
logr logr.Logger | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't have this in a separate package or be exported; that only serves to encourage using it instead of the preferred logging abstraction (logr). IMO this should be a private implementation detail of internal/xds
(or internal/xds/cache
?).
// xDSTest implements the command. | ||
// This is deliberately verbose and unoptimized, since the purpose | ||
// is just to illustrate how the flow will need to work. | ||
func xDSTest() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's roll with the test cmd and create the xds client as part of #177
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
Signed-off-by: Nick Young <[email protected]>
a8a8549
to
fbfb23b
Compare
Fixes #40.
I've made a few related updates here:
internal/xds/cache
to handle the snapshot cache that's required to use go-control-plane.internal/xds/translator
intointernal/types
because I needed it ininternal/cache
.gateway xdstest
command that will run an xDS server for you to connect to to validate this works. This runs through three different IRs and updates the xDS caches with a new translated version every 10 seconds, so that you can see changes run through the system. It's deliberately left way too verbose, since we want to get rid of it anyway.I've got the Delta/incremental xDS stuff to work by having the callbacks manage Envoy nodeIDs and ensure that there's a snapshot per nodeID. This is a bit hacky and should be discussed with go-control-plane to see if there's a better way.
Still todo (I'll log issues for stuff we don't have covered already):
logr
is probably not a good fit for this project, sadly.gateway xdstest
as a command.internal/xds/cache/snapshotcache.go
is the place where that chain of events will begin.