Skip to content

tooling: restoring runtime fatal-by-defaults and changing to fully qualified#9591

Merged
alyssawilk merged 12 commits intoenvoyproxy:masterfrom
alyssawilk:flips_new
Jan 15, 2020
Merged

tooling: restoring runtime fatal-by-defaults and changing to fully qualified#9591
alyssawilk merged 12 commits intoenvoyproxy:masterfrom
alyssawilk:flips_new

Conversation

@alyssawilk
Copy link
Contributor

@alyssawilk alyssawilk commented Jan 7, 2020

Changing from relative name to absolute name, and fixing the fatal-by-defaults that were broken by the v3 switch.

The old way to allow fatal-by-defaults was
envoy.deprecated_features:proto_file.proto:field_name
the new way is
envoy.deprecated_features:full.namespace.field_name

When we switched to v3, all the hard-coded v2 names stopped working. This reinstates them via hopefully more permanent proto annotation.

The only remaining ugly bit is that unfortunately the full namespace and field name are the v3 versions even if the original config was v2. Between @htuch and I we should fix that before merging.

Risk Level: Medium
Testing: added new unit tests
Docs Changes: updated
Release Notes: n/a

…alify

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/.

🐱

Caused by: #9591 was opened by alyssawilk.

see: more, trace.

import "google/protobuf/descriptor.proto";

// Magic number in this file derived from top 28bit of SHA256 digest of "envoy.annotation.do_not_use"
extend google.protobuf.FieldOptions {
Copy link
Member

Choose a reason for hiding this comment

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

Do you mind adding some comments about what these annotations do? I'm a little confused what the proposed flow is?


// Magic number in this file derived from top 28bit of SHA256 digest of "envoy.annotation.do_not_use_enum"
extend google.protobuf.EnumValueOptions {
bool do_not_use_enum = 162744140;
Copy link
Member

Choose a reason for hiding this comment

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

I think you can also call this do_not_use

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think I can.
Things defined in the extend field don't get namespace prefixed. If you notice in the utility file, they're
envoy::annotations::disallowed_by_default_enum
and envoy::annotations::disallowed_by_default
and they conflict if they are both disallowed_by_default

import "google/protobuf/descriptor.proto";

// Magic number in this file derived from top 28bit of SHA256 digest of "envoy.annotation.do_not_use"
extend google.protobuf.FieldOptions {
Copy link
Member

Choose a reason for hiding this comment

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

One other interesting thing here is we're getting awfully close to being able to either encode the runtime key here as an annotation, or via reflection to being able to derive it. Not sure where the status quo there is today. Something worth thinking about, even if it's beyond the scope of this PR.

bool warn_only = false;
#else
bool warn_only = true;
bool warn_only = field->options().GetExtension(envoy::annotations::do_not_use) == false;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: ! rather than ==false

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

No strong opinion on 1, 2 or 3, other than to not violate our existing guidance (so maybe 3 is out).


// Magic number in this file derived from top 28bit of SHA256 digest of "envoy.annotation.do_not_use"
extend google.protobuf.FieldOptions {
bool do_not_use = 169129351;
Copy link
Member

Choose a reason for hiding this comment

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

Bike shedding: prefer to call this disallowed_by_default.

string not_deprecated = 1;
string is_deprecated = 2 [deprecated = true];
string is_deprecated_fatal = 3 [deprecated = true];
string is_deprecated_fatal = 3 [deprecated = true, (envoy.annotations.do_not_use) = true];
Copy link
Member

Choose a reason for hiding this comment

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

So, IIUC, your tooling or manual deprecations will set this on v2. As long as protoxform doesn't delete them (which it might today, ping me tomorrow on how to avoid this), we're good for v3, since the field doesn't exist there.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

I think I addressed reviewer comments.
Still trying to figure out how to propagate the new tags with the proto tools so I can actually annotate things. Prior attempts were wiped out by fix_format :-(

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@mattklein123
Copy link
Member

Thanks this makes sense to me at a high level. Agree either (1) or (2) SGTM.

@alyssawilk
Copy link
Contributor Author

One more meta comment, I think if we're fully qualifying I'm inclined to drop the filename from the name.
When converting things over it turns out at least one thing has changed file locations. I doubt it happens often but if we do that in future we'd break folks' guards.

@mattklein123
Copy link
Member

I think removing filename is reasonable.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

UGH, we have yet another problem.
Because of the way we convert protos, our warning and disabling is now based on whatever Envoy head thinks it's using

so now that we're fully qualifying the v2 test for the deprecated field "runtime key" complains that you're using the deprecated
envoy.deprecated_features:envoy.config.route.v3alpha.RouteAction.RequestMirrorPolicy.hidden_envoy_deprecated_runtime_key

which is pretty terrible, because every time we api upgrade we'll break folks runtime guards

paging in @htuch - even if we dropped the bit where we fully qualify, the field rename from foo to hidden_envoy_foo is pretty crummy.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

Ok, a bit more context for @htuch

This PR is almost good to go.
The problem I'm encountering is visible in test/common/router/config_impl_test.cc
the test sends a v2 API proto, it hits source/common/protobuf/utility.cc
That determines that the v2 field "runtime_key" is no longer allowed and unhelpfully informs the user that they're using envoy.deprecated_features:envoy.config.route.v3alpha.RouteAction.RequestMirrorPolicy.hidden_envoy_deprecated_runtime_key
What would be good is if in checkForUnexpectedFields rather than use
absl::StrCat"envoy.deprecated_features:", field->full_name()),
I could swap full_name for full_original_name per the oracle we discussed.

@htuch
Copy link
Member

htuch commented Jan 8, 2020

@alyssawilk tracking the API oracle work at #9612

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk marked this pull request as ready for review January 8, 2020 22:31
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

LGTM once the stars align. Thanks.

and use of that configuration field will cause the config to be rejected by default.
This fail-by-default mode can be overridden in runtime configuration by setting
envoy.deprecated_features.filename.proto:fieldname or envoy.deprecated_features.filename.proto:enum_value
In the second phase the field will be tagged as disallowed_by_default
Copy link
Member

Choose a reason for hiding this comment

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

Nit: *disallowed_by_default*.

@alyssawilk
Copy link
Contributor Author

Hm, so with @htuch's latest merged, I'm now getting runtime failures unless we flag both the v2 paht and v3 alpha path as OK.
Looking into it....

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Runtime::LoaderSingleton::getExisting()->mergeValues(
{{"envoy.deprecated_features:envoy.extensions.filters.network.redis_proxy.v3alpha.RedisProxy."
"PrefixRoutes.hidden_envoy_deprecated_cluster",
"true"}});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This weirdness is because we're loading deprecated v2 config with a v3 proto. Arguably we should have left the deprecated feature test using a v2 proto rather than envoy::extensions::filters::network::redis_proxy::v3alpha::RedisProxy
Can fix if we care but I'm pretty convinced we don't require both for v3 by the intergration tests not neeting it.

Copy link
Member

Choose a reason for hiding this comment

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

Probably fine for this unit test, we tend to make v3alpha everywhere for unit tests.

Runtime::RuntimeFeaturesPeer::setAllFeaturesAllowed();
// TODO(alyssawilk) improve this.
Runtime::LoaderSingleton::getExisting()->mergeValues(
{{"envoy.deprecated_features:envoy.config.route.v3alpha.CorsPolicy."
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had wanted the PoC PR to show that an integration test using v2 config would succeed with a v2 override.
Unfortunately we switched the integration test framework to v3alpha so we don't have that.

Do we think it's worth doing? My concern is otherwise there might be somewhere in the upgrade protos + downgrade protos pipeline that loses the v2ness, and we'll end up needing double validation as we do with the redis test

Copy link
Member

Choose a reason for hiding this comment

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

@alyssawilk you could try and force the integration test config down to v2 with API_DOWNGRADE macro before passing to Envoy. That would give you a v2 path without changing any code (well, one line :)

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, we have tended to try and force v2 for the xDS aspects of the integration tests with a similar trick, but didn't do this for boostrap. I think it would be a good thing TBH to have the integration tests be focused on v2 external artifacts today.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, as discussed a forced downgrade before we write files to disk fails because the HCM is typed config and we don't have utils for that.

Manual testing looks good. Diff patch for trying bad cors config below, and it gets me whining about v2 CorsPolicy rather than v3. Forcing runtime to accept "envoy.deprecated_features:envoy.api.v2.route.CorsPolicy.enabled" results in the failure turning back to a warning

[2020-01-14 17:12:55.235][90650][warning][misc] [source/common/protobuf/utility.cc:423] Using deprecated option 'envoy.api.v2.route.CorsPolicy.allow_origin' from file route_components.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/intro/deprecated for details.
[2020-01-14 17:12:55.235][90650][critical][main] [source/server/server.cc:94] error initializing configuration 'configs/google_com_proxy.v2.yaml': Proto constraint validation failed (Using deprecated option 'envoy.api.v2.route.CorsPolicy.enabled' from file route_components.proto. This configuration will be removed from Envoy soon. Please see https://www.envoyproxy.io/docs/envoy/latest/intro/deprecated for details. If continued use of this field is absolutely necessary, see https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime#using-runtime-overrides-for-deprecated-features for how to apply a temporary and highly discouraged override.):

--- a/configs/google_com_proxy.v2.yaml
+++ b/configs/google_com_proxy.v2.yaml
@@ -30,6 +30,13 @@ static_resources:
route:
host_rewrite: www.google.com
cluster: service_google

  •              cors:
    
  •                enabled: {}
    
  •                allow_origin: "test-origin-1"
    
  •                allow_origin: "test-host-2"
    
  •                allow_methods: "POST"
    
  •                allow_headers: "content-type"
    
  •                max_age: "100"
         http_filters:
         - name: envoy.router
    
    clusters:
    diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc
    index f10d053b89..24818e60a4 100644
    --- a/source/common/runtime/runtime_impl.cc

Copy link
Member

Choose a reason for hiding this comment

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

Ack, thanks for the verification. We have a reasonable test in protobuf/utility.cc that validates we are doing cross-version deprecation checks (added in my last PR), so I'm reasonably confident based on that this PR is solid.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

// Ideally this would be 'reserved 0' but one can't reserve the default
// value. Instead we throw an exception if this is ever used.
UNSUPPORTED_REST_LEGACY = 0 [deprecated = true];
UNSUPPORTED_REST_LEGACY = 0
Copy link
Member

Choose a reason for hiding this comment

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

I'm kind of surprised this wasn't disabled earlier, we have zero support for this AFAIK.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was disabled, just the old way via the runtime strings :-)

@alyssawilk alyssawilk merged commit 156d7c9 into envoyproxy:master Jan 15, 2020
@alyssawilk alyssawilk deleted the flips_new branch May 18, 2020 14:22
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.

3 participants