Skip to content

core & ios: implement typed configurations & template#328

Merged
rebello95 merged 20 commits intomasterfrom
config-structure
Aug 16, 2019
Merged

core & ios: implement typed configurations & template#328
rebello95 merged 20 commits intomasterfrom
config-structure

Conversation

@rebello95
Copy link
Copy Markdown
Contributor

@rebello95 rebello95 commented Aug 14, 2019

Introduces a Configuration type which consumers will use to start instances of Envoy. This change allows us to:

  • Provide an ergonomic interface for using Envoy Mobile without having to learn Envoy's configuration YAML structure
  • Utilize a solid set of default settings for this library
  • Prevent consumers from accessing features that are unsupported
  • Validate configuration at compile time rather than runtime

This PR:

  • Adds a templated configuration in a .cc file, exposed through the common layer all the way through to the platform layers
  • Adds a Configuration type for accessing this configuration
  • Updates the iOS example apps to use the new typed configuration instead of their own yaml files
  • Maintains an existing initializer for exposing a string configuration for consumers who may still want this functionality

Tests will be added in a separate PR that updates this interface further with a builder for Envoy instances.

Resolves #169.

Related issue (why this is in C++ instead of a yaml resource): #341

Signed-off-by: Michael Rebello me@michaelrebello.com

Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Signed-off-by: Michael Rebello <me@michaelrebello.com>
@rebello95 rebello95 marked this pull request as ready for review August 16, 2019 18:45
@rebello95 rebello95 requested a review from goaway August 16, 2019 18:45
@rebello95 rebello95 changed the title wip: typed/templated configurations core & ios: implement typed configurations & template Aug 16, 2019
Signed-off-by: Michael Rebello <me@michaelrebello.com>
Copy link
Copy Markdown
Member

@junr03 junr03 left a comment

Choose a reason for hiding this comment

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

I have a general concern with this approach. Sorry I had not voiced it earlier, I was catching up to this.

If we structure the configuration in swift we are opening up the gates for having to do the same in every language we want to support. In addition we are creating a new API surface for envoy configuration. i.e the "Envoy Mobile" subset of Envoy configuration, and thus every time we need to support something new or deprecate a field we need to go and do so in every language we support.

The Network team at Lyft has struggled in the past with providing a subset API and it has come with several maintenance headaches.

What are your thoughts about maintenance of this typed configuration approach?

Signed-off-by: Michael Rebello <me@michaelrebello.com>
@rebello95
Copy link
Copy Markdown
Contributor Author

If we structure the configuration in swift we are opening up the gates for having to do the same in every language we want to support.

I outlined some of the concerns with a purely string-based approach in the linked issue, but to add some more color:

  • Envoy Mobile supports a small subset of the configurations that are available in upstream Envoy. This will likely always be the case, and going outside those configurations can cause undefined behavior at runtime. Using types can help alleviate this
  • Having consumers manually load configuration file resources and pass them to Envoy Mobile at runtime is additional overhead and can lead to bugs discovered at runtime instead of build time (invalid config files, mis-loading resources, etc.)
  • Envoy's current configurations are non-trivial and require a learning curve to be able to use them at all. The status quo of networking libraries on mobile generally requires little up-front configuration cost, and we should try to match that here to encourage wider adoption
  • Supporting this in each language (currently Swift/Kotlin) does amount to some overhead, but that can be said about every other aspect of the library as well (i.e., Envoy Mobile isn't all C++ 😄)

What are your thoughts about maintenance of this typed configuration approach?

  • Configs will be forwards compatible. Using a builder pattern on both platforms will allow us to add new defaults without making consumers update their code unless they want to take advantage of the new features
  • On the other hand, we can always deprecate/remove options from the configuration if necessary (especially pre-1.0), and consumers will find out at build time rather than when loading a config file at runtime

In summary: I think the reduced barrier to entry, ease of use, and simplicity of typed configurations far out-weighs the minimal maintenance cost this will incur.

@junr03
Copy link
Copy Markdown
Member

junr03 commented Aug 16, 2019

Thanks for that explanation. It goes to show my bias from the far more complex land of service mesh configurations. I think all the reasons listed above really assuage any immediate concerns I have with this approach :)

Envoy's current configurations are non-trivial and require a learning curve to be able to use them at all. The status quo of networking libraries on mobile generally requires little up-front configuration cost, and we should try to match that here to encourage wider adoption.

This specially makes me agree with the approach taken here. And reminds me that a very similar pattern is being used in cronet; with, as you say here, a very small configuration surface.

@goaway
Copy link
Copy Markdown
Contributor

goaway commented Aug 16, 2019

I talked with @junr03 a bit about this offline. In general, while I think @junr03's concerns merit consideration, I tend to agree with @rebello95's points above. To summarize a couple of the things we discussed:

I think the challenges the Network Team has faced are a bit beyond the scope of what we'll encounter here. The configuration of Lyft's mesh is far more complex than our default template configuration will ever have to be.

The proto generation, serialization and deserialization that would be required to support the proto based approach is a fair amount of overhead, whereas string interpolation is cheap, and at least for a smaller set of configurable touch points, easy.

Finally, I think we can avoid the risks of implementing across languages by having the templating be well-documented. If this ends up being a pain point, we can also consider migrating templating logic down into the common layer at some point down the road.

@rebello95
Copy link
Copy Markdown
Contributor Author

Finally, I think we can avoid the risks of implementing across languages by having the templating be well-documented. If this ends up being a pain point, we can also consider migrating templating logic down into the common layer at some point down the road.

Yep I think documenting this is very valuable, and we can also use upstream Envoy's comprehensive docs as a point of reference here too. I also think it's useful to allow consumers to instantiate Envoy Mobile instances using raw string files (which is maintained in this PR), for those who are interested in doing something ultra-customized.

@implementation EnvoyConfiguration

+ (NSString *)templateString {
return [[NSString alloc] initWithUTF8String:config_template];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: how about putting

static NSString * const kEnvoyTemplateString = [[NSString alloc] initWithUTF8String:config_template];

above the @implementation and then just returning that each time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately this doesn't work since we hit the following error:

Initializer element is not a compile-time constant

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, makes sense. Silly, since of course it is constant at compile-time, but I understand the limitations at this scope.

You could work around this by using #define instead of the extern'd const... but, let's not worry about it.

@goaway
Copy link
Copy Markdown
Contributor

goaway commented Aug 16, 2019

Implementation looks great; just a couple minor suggestions.

Signed-off-by: Michael Rebello <me@michaelrebello.com>
Copy link
Copy Markdown
Contributor

@goaway goaway left a comment

Choose a reason for hiding this comment

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

Nice work.

@rebello95 rebello95 merged commit 6c1b81b into master Aug 16, 2019
@rebello95 rebello95 deleted the config-structure branch August 16, 2019 21:24
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.

ios/android: configuration structures for starting Envoy

3 participants