Signed-off-by: Harvey Tuch <htuch@google.com>
This commit is contained in:
Harvey Tuch 2019-08-15 08:28:39 -04:00
parent f5b536d834
commit bc7cec3974
16 changed files with 448 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bazel-*

9
WORKSPACE Normal file
View File

@ -0,0 +1,9 @@
workspace(name = "com_github_cncf_udpa")
load("//bazel:repositories.bzl", "udpa_api_dependencies")
udpa_api_dependencies()
load("//bazel:dependency_imports.bzl", "udpa_dependency_imports")
udpa_dependency_imports()

0
bazel/BUILD Normal file
View File

104
bazel/api_build_system.bzl Normal file
View File

@ -0,0 +1,104 @@
load("@com_google_protobuf//:protobuf.bzl", _py_proto_library = "py_proto_library")
load("@com_envoyproxy_protoc_gen_validate//bazel:pgv_proto_library.bzl", "pgv_cc_proto_library")
_PY_SUFFIX = "_py"
_CC_SUFFIX = "_cc"
def _Suffix(d, suffix):
return d + suffix
def _LibrarySuffix(library_name, suffix):
# Transform //a/b/c to //a/b/c:c in preparation for suffix operation below.
if library_name.startswith("//") and ":" not in library_name:
library_name += ":" + Label(library_name).name
return _Suffix(library_name, suffix)
# TODO(htuch): has_services is currently ignored but will in future support
# gRPC stub generation.
# TODO(htuch): Add support for Go based on envoy_api as needed.
def udpa_proto_library(
name,
visibility = ["//visibility:private"],
srcs = [],
deps = [],
has_services = None):
native.proto_library(
name = name,
srcs = srcs,
deps = deps + [
"@com_google_protobuf//:any_proto",
"@com_google_protobuf//:descriptor_proto",
"@com_google_protobuf//:duration_proto",
"@com_google_protobuf//:empty_proto",
"@com_google_protobuf//:struct_proto",
"@com_google_protobuf//:timestamp_proto",
"@com_google_protobuf//:wrappers_proto",
"@com_google_googleapis//google/api:http_proto",
"@com_google_googleapis//google/api:annotations_proto",
"@com_google_googleapis//google/rpc:status_proto",
"@com_envoyproxy_protoc_gen_validate//validate:validate_proto",
],
visibility = visibility,
)
pgv_cc_proto_library(
name = _Suffix(name, _CC_SUFFIX),
cc_deps = [_LibrarySuffix(d, _CC_SUFFIX) for d in deps] + [
"@com_google_googleapis//google/api:http_cc_proto",
"@com_google_googleapis//google/api:annotations_cc_proto",
"@com_google_googleapis//google/rpc:status_cc_proto",
],
deps = [":" + name],
visibility = visibility,
)
py_export_suffixes = []
_py_proto_library(
name = _Suffix(name, _PY_SUFFIX),
srcs = srcs,
default_runtime = "@com_google_protobuf//:protobuf_python",
protoc = "@com_google_protobuf//:protoc",
deps = [_LibrarySuffix(d, _PY_SUFFIX) for d in deps] + [
"@com_envoyproxy_protoc_gen_validate//validate:validate_py",
"@com_google_googleapis//google/rpc:status_py_proto",
"@com_google_googleapis//google/api:annotations_py_proto",
"@com_google_googleapis//google/api:http_py_proto",
"@com_google_googleapis//google/api:httpbody_py_proto",
],
visibility = visibility,
)
py_export_suffixes = ["_py", "_py_genproto"]
# Allow unlimited visibility for consumers
export_suffixes = ["", "_cc", "_cc_validate"] + py_export_suffixes
for s in export_suffixes:
native.alias(
name = name + "_export" + s,
actual = name + s,
visibility = ["//visibility:public"],
)
def udpa_cc_test(name, srcs, proto_deps):
native.cc_test(
name = name,
srcs = srcs,
deps = [_LibrarySuffix(d + "_export", _CC_SUFFIX) for d in proto_deps],
)
# This defines googleapis py_proto_library. The repository does not provide its definition and requires
# overriding it in the consuming project (see https://github.com/grpc/grpc/issues/19255 for more details).
def py_proto_library(name, deps = []):
srcs = [dep[:-6] + ".proto" if dep.endswith("_proto") else dep for dep in deps]
proto_deps = []
# py_proto_library in googleapis specifies *_proto rules in dependencies.
# By rewriting *_proto to *.proto above, the dependencies in *_proto rules are not preserved.
# As a workaround, manually specify the proto dependencies for the imported python rules.
if name == "annotations_py_proto":
proto_deps = proto_deps + [":http_py_proto"]
_py_proto_library(
name = name,
srcs = srcs,
default_runtime = "@com_google_protobuf//:protobuf_python",
protoc = "@com_google_protobuf//:protoc",
deps = proto_deps + ["@com_google_protobuf//:protobuf_python"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,23 @@
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
# go version for rules_go
GO_VERSION = "1.12.8"
def udpa_dependency_imports(go_version = GO_VERSION):
rules_foreign_cc_dependencies()
go_rules_dependencies()
go_register_toolchains(go_version)
gazelle_dependencies()
switched_rules_by_language(
name = "com_google_googleapis_imports",
cc = True,
go = True,
grpc = True,
rules_override = {
"py_proto_library": "@com_github_cncf_udpa//bazel:api_build_system.bzl",
},
)

View File

@ -0,0 +1,24 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
def udpa_http_archive(name, locations, **kwargs):
# `existing_rule_keys` contains the names of repositories that have already
# been defined in the Bazel workspace. By skipping repos with existing keys,
# users can override dependency versions by using standard Bazel repository
# rules in their WORKSPACE files.
existing_rule_keys = native.existing_rules().keys()
if name in existing_rule_keys:
# This repository has already been defined, probably because the user
# wants to override the version. Do nothing.
return
loc_key = kwargs.pop("repository_key", name)
location = locations[loc_key]
# HTTP tarball at a given URL. Add a BUILD file if requested.
http_archive(
name = name,
urls = location["urls"],
sha256 = location["sha256"],
strip_prefix = location.get("strip_prefix", ""),
**kwargs
)

13
bazel/foreign_cc/BUILD Normal file
View File

@ -0,0 +1,13 @@
load("@rules_foreign_cc//tools/build_defs:cmake.bzl", "cmake_external")
cmake_external(
name = "zlib",
cache_entries = {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
},
lib_source = "@net_zlib//:all",
static_libraries = select({
"//conditions:default": ["libz.a"],
}),
visibility = ["//visibility:public"],
)

33
bazel/protobuf.patch Normal file
View File

@ -0,0 +1,33 @@
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 3844fa6b8b..5486887295 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -1065,10 +1065,12 @@ char* FastUInt32ToBufferLeft(uint32 u, char* buffer) {
}
char* FastInt32ToBufferLeft(int32 i, char* buffer) {
- uint32 u = i;
+ uint32 u = 0;
if (i < 0) {
*buffer++ = '-';
- u = -i;
+ u -= i;
+ } else {
+ u = i;
}
return FastUInt32ToBufferLeft(u, buffer);
}
diff --git a/BUILD b/BUILD
index 6665de94..55f28582 100644
--- a/BUILD
+++ b/BUILD
@@ -19,6 +19,6 @@ config_setting(
# ZLIB configuration
################################################################################
-ZLIB_DEPS = ["@zlib//:zlib"]
+ZLIB_DEPS = ["//external:zlib"]
################################################################################
# Protobuf Runtime Library

65
bazel/repositories.bzl Normal file
View File

@ -0,0 +1,65 @@
load(":envoy_http_archive.bzl", "udpa_http_archive")
load(":repository_locations.bzl", "REPOSITORY_LOCATIONS")
# Make all contents of an external repository accessible under a filegroup. Used for external HTTP
# archives, e.g. cares.
BUILD_ALL_CONTENT = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
def udpa_api_dependencies():
udpa_http_archive(
"bazel_gazelle",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
"bazel_skylib",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
"com_envoyproxy_protoc_gen_validate",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
name = "com_github_grpc_grpc",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
name = "com_google_googleapis",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
"com_google_protobuf",
locations = REPOSITORY_LOCATIONS,
# The patch includes
# https://github.com/protocolbuffers/protobuf/pull/6333 and also uses
# foreign_cc build for zlib as its dependency.
# TODO(asraa): remove this when > protobuf 3.8.0 is released.
patch_args = ["-p1"],
patches = ["//bazel:protobuf.patch"],
)
udpa_http_archive(
"io_bazel_rules_go",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
name = "rules_foreign_cc",
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
name = "net_zlib",
build_file_content = BUILD_ALL_CONTENT,
locations = REPOSITORY_LOCATIONS,
)
udpa_http_archive(
name = "six_archive",
build_file = "@com_google_protobuf//:six.BUILD",
locations = REPOSITORY_LOCATIONS,
)
# Misc. rebinds
native.bind(
name = "six",
actual = "@six_archive//:six",
)
native.bind(
name = "zlib",
actual = "//bazel/foreign_cc:zlib",
)

View File

@ -0,0 +1,51 @@
REPOSITORY_LOCATIONS = dict(
bazel_gazelle = dict(
sha256 = "be9296bfd64882e3c08e3283c58fcb461fa6dd3c171764fcc4cf322f60615a9b",
urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.18.1/bazel-gazelle-0.18.1.tar.gz"],
),
bazel_skylib = dict(
sha256 = "2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e",
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/0.8.0/bazel-skylib.0.8.0.tar.gz"],
),
com_envoyproxy_protoc_gen_validate = dict(
sha256 = "ddefe3dcbb25d68a2e5dfea67d19c060959c2aecc782802bd4c1a5811d44dd45",
strip_prefix = "protoc-gen-validate-2feaabb13a5d697b80fcb938c0ce37b24c9381ee", # Jul 26, 2018
urls = ["https://github.com/envoyproxy/protoc-gen-validate/archive/2feaabb13a5d697b80fcb938c0ce37b24c9381ee.tar.gz"],
),
com_github_grpc_grpc = dict(
sha256 = "bcb01ac7029a7fb5219ad2cbbc4f0a2df3ef32db42e236ce7814597f4b04b541",
strip_prefix = "grpc-79a8b5289e3122d2cea2da3be7151d37313d6f46",
# Commit from 2019-05-30
urls = ["https://github.com/grpc/grpc/archive/79a8b5289e3122d2cea2da3be7151d37313d6f46.tar.gz"],
),
com_google_googleapis = dict(
# TODO(dio): Consider writing a Skylark macro for importing Google API proto.
sha256 = "c1969e5b72eab6d9b6cfcff748e45ba57294aeea1d96fd04cd081995de0605c2",
strip_prefix = "googleapis-be480e391cc88a75cf2a81960ef79c80d5012068",
urls = ["https://github.com/googleapis/googleapis/archive/be480e391cc88a75cf2a81960ef79c80d5012068.tar.gz"],
),
com_google_protobuf = dict(
sha256 = "b7220b41481011305bf9100847cf294393973e869973a9661046601959b2960b",
strip_prefix = "protobuf-3.8.0",
urls = ["https://github.com/protocolbuffers/protobuf/releases/download/v3.8.0/protobuf-all-3.8.0.tar.gz"],
),
io_bazel_rules_go = dict(
sha256 = "96b1f81de5acc7658e1f5a86d7dc9e1b89bc935d83799b711363a748652c471a",
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.19.2/rules_go-0.19.2.tar.gz"],
),
rules_foreign_cc = dict(
sha256 = "c957e6663094a1478c43330c1bbfa71afeaf1ab86b7565233783301240c7a0ab",
strip_prefix = "rules_foreign_cc-a209b642c7687a8894c19b3dd40e43e6d3f38e83",
# 2019-07-17
urls = ["https://github.com/bazelbuild/rules_foreign_cc/archive/a209b642c7687a8894c19b3dd40e43e6d3f38e83.tar.gz"],
),
net_zlib = dict(
sha256 = "629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff",
strip_prefix = "zlib-1.2.11",
urls = ["https://github.com/madler/zlib/archive/v1.2.11.tar.gz"],
),
six_archive = dict(
sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
urls = ["https://files.pythonhosted.org/packages/b3/b2/238e2590826bfdd113244a40d9d3eb26918bd798fc187e2360a8367068db/six-1.10.0.tar.gz"],
),
)

11
test/build/BUILD Normal file
View File

@ -0,0 +1,11 @@
load("//bazel:api_build_system.bzl", "udpa_cc_test")
licenses(["notice"]) # Apache 2
udpa_cc_test(
name = "build_test",
srcs = ["build_test.cc"],
proto_deps = [
"//udpa/service/orca/v1:orca",
],
)

21
test/build/build_test.cc Normal file
View File

@ -0,0 +1,21 @@
// NOLINT(namespace-envoy)
#include <cstdlib>
#include <iostream>
#include "google/protobuf/descriptor.h"
// Basic C++ build/link validation for the v2 xDS APIs.
int main(int argc, char* argv[]) {
const auto methods = {
"udpa.service.orca.v1.OpenRcaService.StreamCoreMetrics",
};
for (const auto& method : methods) {
if (google::protobuf::DescriptorPool::generated_pool()->FindMethodByName(method) == nullptr) {
std::cout << "Unable to find method descriptor for " << method << std::endl;
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}

9
udpa/data/orca/v1/BUILD Normal file
View File

@ -0,0 +1,9 @@
load("//bazel:api_build_system.bzl", "udpa_proto_library")
licenses(["notice"]) # Apache 2
udpa_proto_library(
name = "orca_load_report",
srcs = ["orca_load_report.proto"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,36 @@
syntax = "proto3";
package udpa.data.orca.v1;
option java_outer_classname = "OrcaLoadReportProto";
option java_multiple_files = true;
option java_package = "com.github.udpa.udpa.data.orca.v1";
option go_package = "v1";
import "validate/validate.proto";
// See section `ORCA load report format` of the design document in
// :ref:`https://github.com/envoyproxy/envoy/issues/6614`.
message OrcaLoadReport {
// CPU utilization expressed as a fraction of available CPU resources. This
// should be derived from the latest sample or measurement.
double cpu_utilization = 1 [(validate.rules).double.gte = 0, (validate.rules).double.lte = 1];
// Memory utilization expressed as a fraction of available memory
// resources. This should be derived from the latest sample or measurement.
double mem_utilization = 2 [(validate.rules).double.gte = 0, (validate.rules).double.lte = 1];
// Total RPS being served by an endpoint. This should cover all services that an endpoint is
// responsible for.
uint64 rps = 3;
// Application specific requests costs. Each value is an absolute cost (e.g. 3487 bytes of
// storage) associated with the request.
map<string, double> request_cost = 4;
// Resource utilization values. Each value is expressed as a fraction of total resources
// available, derived from the latest sample or measurement.
map<string, double> utilization = 5
[(validate.rules).map.values.double.gte = 0, (validate.rules).map.values.double.lte = 1];
}

View File

@ -0,0 +1,10 @@
load("//bazel:api_build_system.bzl", "udpa_proto_library")
licenses(["notice"]) # Apache 2
udpa_proto_library(
name = "orca",
srcs = ["orca.proto"],
has_services = 1,
deps = ["//udpa/data/orca/v1:orca_load_report"],
)

View File

@ -0,0 +1,38 @@
syntax = "proto3";
package udpa.service.orca.v1;
option java_outer_classname = "OrcaProto";
option java_multiple_files = true;
option java_package = "com.github.udpa.udpa.service.orca.v1";
option go_package = "v1";
import "udpa/data/orca/v1/orca_load_report.proto";
import "google/protobuf/duration.proto";
import "validate/validate.proto";
// See section `Out-of-band (OOB) reporting` of the design document in
// :ref:`https://github.com/envoyproxy/envoy/issues/6614`.
// Out-of-band (OOB) load reporting service for the additional load reporting
// agent that does not sit in the request path. Reports are periodically sampled
// with sufficient frequency to provide temporal association with requests.
// OOB reporting compensates the limitation of in-band reporting in revealing
// costs for backends that do not provide a steady stream of telemetry such as
// long running stream operations and zero QPS services. This is a server
// streaming service, client needs to terminate current RPC and initiate
// a new call to change backend reporting frequency.
service OpenRcaService {
rpc StreamCoreMetrics(OrcaLoadReportRequest) returns (stream udpa.data.orca.v1.OrcaLoadReport);
}
message OrcaLoadReportRequest {
// Interval for generating Open RCA core metric responses.
google.protobuf.Duration report_interval = 1;
// Request costs to collect. If this is empty, all known requests costs tracked by
// the load reporting agent will be returned. This provides an opportunity for
// the client to selectively obtain a subset of tracked costs.
repeated string request_cost_names = 2;
}