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

extension: use bool_flag to control extension link #14240

Merged
merged 5 commits into from
Dec 8, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions bazel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -658,17 +658,30 @@ The following optional features can be enabled on the Bazel build command-line:
* Envoy can be linked to [`zlib-ng`](https://github.com/zlib-ng/zlib-ng) instead of
[`zlib`](https://zlib.net) with `--define zlib=ng`.

## Disabling extensions
## Enabling and disabling extensions

Envoy uses a modular build which allows extensions to be removed if they are not needed or desired.
Extensions that can be removed are contained in
[extensions_build_config.bzl](../source/extensions/extensions_build_config.bzl). Use the following
procedure to customize the extensions for your build:
[extensions_build_config.bzl](../source/extensions/extensions_build_config.bzl).

The extensions disabled by default can be enabled by adding the following parameter to Bazel, for example to enable
`envoy.filters.http.kill_request` extension, add `--//source/extensions/filters/http/kill_request:enabled`.
The extensions enabled by default can be disabled by adding the following parameter to Bazel, for example to disable
`envoy.wasm.runtime.v8` extension, add `--//source/extensions/wasm_runtime/v8:enabled=false`.
Note not all extensions can be disabled.

If you're building from a custom build repository, the parameters need to prefixed with `@envoy`, for example
`--@envoy//source/extensions/filters/http/kill_request:enabled`.

You may persist those options in `user.bazelrc` in Envoy repo or your `.bazelrc`.

## Customize extension build config

You can also use the following procedure to customize the extensions for your build:

* The Envoy build assumes that a Bazel repository named `@envoy_build_config` exists which
contains the file `@envoy_build_config//:extensions_build_config.bzl`. In the default build,
a synthetic repository is created containing [extensions_build_config.bzl](../source/extensions/extensions_build_config.bzl).
Thus, the default build has all extensions.
* Start by creating a new Bazel workspace somewhere in the filesystem that your build can access.
This workspace should contain:
* Empty WORKSPACE file.
Expand All @@ -683,7 +696,7 @@ To have your local build use your overridden configuration repository there are
2. Use the following snippet in your WORKSPACE before you load the Envoy repository. E.g.,

```
workspace(name = "envoy")
workspace(name = "envoy_filter_example")

local_repository(
name = "envoy_build_config",
Expand Down
13 changes: 12 additions & 1 deletion bazel/envoy_build_system.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,24 @@ load(
"@envoy_build_config//:extensions_build_config.bzl",
"EXTENSION_PACKAGE_VISIBILITY",
)
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")

def envoy_package():
native.package(default_visibility = ["//visibility:public"])

def envoy_extension_package():
def envoy_extension_package(enabled_default = True):
native.package(default_visibility = EXTENSION_PACKAGE_VISIBILITY)

bool_flag(
name = "enabled",
build_setting_default = enabled_default,
)

native.config_setting(
name = "is_enabled",
flag_values = {":enabled": "True"},
)

# A genrule variant that can output a directory. This is useful when doing things like
# generating a fuzz corpus mechanically.
def _envoy_directory_genrule_impl(ctx):
Expand Down
17 changes: 16 additions & 1 deletion bazel/envoy_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,22 @@ def envoy_cc_extension(
fail("Unknown extension status: " + status)
if "//visibility:public" not in visibility:
visibility = visibility + extra_visibility
envoy_cc_library(name, tags = tags, visibility = visibility, **kwargs)

ext_name = name + "_envoy_extension"
envoy_cc_library(
name = name,
tags = tags,
visibility = visibility,
**kwargs
)
cc_library(
name = ext_name,
deps = select({
":is_enabled": [":" + name],
"//conditions:default": [],
}),
visibility = visibility,
)

# Envoy C++ library targets should be specified with this function.
def envoy_cc_library(
Expand Down
2 changes: 2 additions & 0 deletions bazel/envoy_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,14 @@ def envoy_cc_test(
tags = [],
args = [],
copts = [],
condition = None,
shard_count = None,
coverage = True,
local = False,
size = "medium",
flaky = False):
coverage_tags = tags + ([] if coverage else ["nocoverage"])

cc_test(
name = name,
srcs = srcs,
Expand Down
4 changes: 1 addition & 3 deletions docs/generate_extension_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,9 @@ def GetExtensionMetadata(target):
if __name__ == '__main__':
output_path = sys.argv[1]
extension_db = {}
# Include all extensions from both EXTENSIONS and
# DISABLED_BY_DEFAULT_EXTENSIONS in source/extensions/extensions_build_config.bzl
# Include all extensions from source/extensions/extensions_build_config.bzl
all_extensions = {}
all_extensions.update(extensions_build_config.EXTENSIONS)
all_extensions.update(extensions_build_config.DISABLED_BY_DEFAULT_EXTENSIONS)
for extension, target in all_extensions.items():
extension_db[extension] = GetExtensionMetadata(target)
# The TLS and generic upstream extensions are hard-coded into the build, so
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Kill Request
===============

The KillRequest filter can be used to crash Envoy when receiving a Kill request.
By default, KillRequest filter is not built into Envoy binary since it is included in *DISABLED_BY_DEFAULT_EXTENSIONS* in *extensions_build_config.bzl*. If you want to use this extension, please move it from *DISABLED_BY_DEFAULT_EXTENSIONS* to *EXTENSIONS*.
By default, KillRequest filter is not built into Envoy binary. If you want to use this extension,
build Envoy with `--//source/extensions/filters/http/kill_request:enabled`.

Configuration
-------------
Expand Down
16 changes: 8 additions & 8 deletions source/extensions/all_extensions.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("@envoy_build_config//:extensions_build_config.bzl", "DISABLED_BY_DEFAULT_EXTENSIONS", "EXTENSIONS")

GLOBAL_DENYLIST = DISABLED_BY_DEFAULT_EXTENSIONS.keys()
load("@envoy_build_config//:extensions_build_config.bzl", "EXTENSIONS")

# These extensions are registered using the extension system but are required for the core Envoy build.
# The map may be overridden by extensions specified in envoy_build_config.
Expand All @@ -10,14 +8,16 @@ _required_extensions = {
"envoy.transport_sockets.tls": "//source/extensions/transport_sockets/tls:config",
}

# Return the extension cc_library target after select
def _selected_extension_target(target):
return target + "_envoy_extension"

# Return all extensions to be compiled into Envoy.
def envoy_all_extensions(denylist = []):
all_extensions = dicts.add(_required_extensions, EXTENSIONS)

denylist = denylist + GLOBAL_DENYLIST

# These extensions can be removed on a site specific basis.
return [v for k, v in all_extensions.items() if not k in denylist]
return [_selected_extension_target(v) for k, v in all_extensions.items() if not k in denylist]

# Core extensions needed to run Envoy's integration tests.
_core_extensions = [
Expand All @@ -41,7 +41,7 @@ _http_filter_prefix = "envoy.filters.http"
def envoy_all_http_filters():
all_extensions = dicts.add(_required_extensions, EXTENSIONS)

return [v for k, v in all_extensions.items() if k.startswith(_http_filter_prefix) and k not in GLOBAL_DENYLIST]
return [_selected_extension_target(v) for k, v in all_extensions.items() if k.startswith(_http_filter_prefix)]

# All network-layer filters are extensions with names that have the following prefix.
_network_filter_prefix = "envoy.filters.network"
Expand All @@ -53,4 +53,4 @@ _thrift_filter_prefix = "envoy.filters.thrift"
def envoy_all_network_filters():
all_extensions = dicts.add(_required_extensions, EXTENSIONS)

return [v for k, v in all_extensions.items() if (k.startswith(_network_filter_prefix) or k.startswith(_thrift_filter_prefix)) and k not in GLOBAL_DENYLIST]
return [_selected_extension_target(v) for k, v in all_extensions.items() if (k.startswith(_network_filter_prefix) or k.startswith(_thrift_filter_prefix))]
9 changes: 3 additions & 6 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ EXTENSIONS = {
"envoy.filters.http.health_check": "//source/extensions/filters/http/health_check:config",
"envoy.filters.http.ip_tagging": "//source/extensions/filters/http/ip_tagging:config",
"envoy.filters.http.jwt_authn": "//source/extensions/filters/http/jwt_authn:config",
# Disabled by default
"envoy.filters.http.kill_request": "//source/extensions/filters/http/kill_request:kill_request_config",
"envoy.filters.http.local_ratelimit": "//source/extensions/filters/http/local_ratelimit:config",
"envoy.filters.http.lua": "//source/extensions/filters/http/lua:config",
"envoy.filters.http.oauth2": "//source/extensions/filters/http/oauth2:config",
"envoy.filters.http.oauth2": "//source/extensions/filters/http/oauth2:config",
"envoy.filters.http.on_demand": "//source/extensions/filters/http/on_demand:config",
"envoy.filters.http.original_src": "//source/extensions/filters/http/original_src:config",
"envoy.filters.http.ratelimit": "//source/extensions/filters/http/ratelimit:config",
Expand Down Expand Up @@ -227,11 +229,6 @@ EXTENSIONS = {
"envoy.wasm.runtime.wasmtime": "//source/extensions/wasm_runtime/wasmtime:config",
}

# These filters will not be built into Envoy by default. To build Envoy with any of these filter, please move it to EXTENSIONS.
DISABLED_BY_DEFAULT_EXTENSIONS = {
"envoy.filters.http.kill_request": "//source/extensions/filters/http/kill_request:kill_request_config",
}

# These can be changed to ["//visibility:public"], for downstream builds which
# need to directly reference Envoy extensions.
EXTENSION_CONFIG_VISIBILITY = ["//:extension_config"]
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/filters/http/kill_request/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ load(

licenses(["notice"]) # Apache 2

envoy_extension_package()
envoy_extension_package(enabled_default = False)

envoy_cc_library(
name = "kill_request_filter_lib",
Expand Down
41 changes: 13 additions & 28 deletions test/extensions/extensions_build_system.bzl
Original file line number Diff line number Diff line change
@@ -1,62 +1,47 @@
load("//bazel:envoy_build_system.bzl", "envoy_benchmark_test", "envoy_cc_benchmark_binary", "envoy_cc_mock", "envoy_cc_test", "envoy_cc_test_binary", "envoy_cc_test_library")
load("@envoy_build_config//:extensions_build_config.bzl", "DISABLED_BY_DEFAULT_EXTENSIONS", "EXTENSIONS")
load("@envoy_build_config//:extensions_build_config.bzl", "EXTENSIONS")

def extension_allowed_for_test(extension_name):
return extension_name in EXTENSIONS or extension_name in DISABLED_BY_DEFAULT_EXTENSIONS
def _skip_extension(func, name, extension_name, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

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

This name is a bit confusing, maybe apply_to_extension_allow_for_test or something.

if not extension_name in EXTENSIONS:
return

func(name, **kwargs)

# All extension tests should use this version of envoy_cc_test(). It allows compiling out
# tests for extensions that the user does not wish to include in their build.
# @param extension_name should match an extension listed in EXTENSIONS or DISABLED_BY_DEFAULT_EXTENSIONS.
# @param extension_name should match an extension listed in EXTENSIONS.
def envoy_extension_cc_test(
name,
extension_name,
**kwargs):
if not extension_allowed_for_test(extension_name):
return

envoy_cc_test(name, **kwargs)
_skip_extension(envoy_cc_test, name, extension_name, **kwargs)

def envoy_extension_cc_test_library(
name,
extension_name,
**kwargs):
if not extension_allowed_for_test(extension_name):
return

envoy_cc_test_library(name, **kwargs)
_skip_extension(envoy_cc_test_library, name, extension_name, **kwargs)

def envoy_extension_cc_mock(
name,
extension_name,
**kwargs):
if not extension_allowed_for_test(extension_name):
return

envoy_cc_mock(name, **kwargs)
_skip_extension(envoy_cc_mock, name, extension_name, **kwargs)

def envoy_extension_cc_test_binary(
name,
extension_name,
**kwargs):
if not extension_allowed_for_test(extension_name):
return

envoy_cc_test_binary(name, **kwargs)
_skip_extension(envoy_cc_test_binary, name, extension_name, **kwargs)

def envoy_extension_cc_benchmark_binary(
name,
extension_name,
**kwargs):
if not extension_allowed_for_test(extension_name):
return

envoy_cc_benchmark_binary(name, **kwargs)
_skip_extension(envoy_cc_benchmark_binary, name, extension_name, **kwargs)

def envoy_extension_benchmark_test(
name,
extension_name,
**kwargs):
if not extension_allowed_for_test(extension_name):
return

envoy_benchmark_test(name, **kwargs)
_skip_extension(envoy_benchmark_test, name, extension_name, **kwargs)
2 changes: 1 addition & 1 deletion tools/code_format/envoy_build_fixer.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def FixPackageAndLicense(path, contents):
# Envoy package is inserted after the load block containing the
# envoy_package import.
package_and_parens = package_string + '()'
if package_and_parens not in contents:
if package_and_parens[:-1] not in contents:
contents = re.sub(regex_to_use, r'\1\n%s\n\n' % package_and_parens, contents)
if package_and_parens not in contents:
raise EnvoyBuildFixerError('Unable to insert %s' % package_and_parens)
Expand Down
5 changes: 1 addition & 4 deletions tools/dependency/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,7 @@ def ListExtensions(self):
Returns:
Dictionary items from source/extensions/extensions_build_config.bzl.
"""
all_extensions = {}
all_extensions.update(extensions_build_config.EXTENSIONS)
all_extensions.update(extensions_build_config.DISABLED_BY_DEFAULT_EXTENSIONS)
return all_extensions.items()
return extensions_build_config.EXTENSIONS.items()


class Validator(object):
Expand Down