mirror of https://github.com/grpc/grpc.git
[GCP auth filter] add "blackboard" mechanism for retaining global state, and use it for cache in GCP auth filter (#37646)
This is the last piece of gRFC A83 (https://github.com/grpc/proposal/pull/438).
Note that although this is the first use-case for this "blackboard" mechanism, we will also use it in the future for the xDS rate-limiting filter on the gRPC server side.
Closes #37646
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37646 from markdroth:gcp_auth_filter_state 72d0d96c79
PiperOrigin-RevId: 679707134
pull/37584/head
parent
6dbc0bdb10
commit
e56d766a45
37 changed files with 675 additions and 59 deletions
@ -0,0 +1,33 @@ |
||||
//
|
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include "src/core/filter/blackboard.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
RefCountedPtr<Blackboard::Entry> Blackboard::Get(UniqueTypeName type, |
||||
const std::string& key) const { |
||||
auto it = map_.find(std::make_pair(type, key)); |
||||
if (it == map_.end()) return nullptr; |
||||
return it->second; |
||||
} |
||||
|
||||
void Blackboard::Set(UniqueTypeName type, const std::string& key, |
||||
RefCountedPtr<Entry> entry) { |
||||
map_[std::make_pair(type, key)] = std::move(entry); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,71 @@ |
||||
//
|
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef GRPC_SRC_CORE_FILTER_BLACKBOARD_H |
||||
#define GRPC_SRC_CORE_FILTER_BLACKBOARD_H |
||||
|
||||
#include <string> |
||||
#include <utility> |
||||
|
||||
#include "absl/container/flat_hash_map.h" |
||||
#include "absl/strings/string_view.h" |
||||
|
||||
#include "src/core/resolver/endpoint_addresses.h" |
||||
#include "src/core/util/debug_location.h" |
||||
#include "src/core/util/ref_counted.h" |
||||
#include "src/core/util/ref_counted_ptr.h" |
||||
#include "src/core/util/unique_type_name.h" |
||||
#include "src/core/util/useful.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// A blackboard is a place where dynamic filters can stash global state
|
||||
// that they may want to retain across resolver updates. Entries are
|
||||
// identified by by the unique type and a name that identifies the instance,
|
||||
// which means that it's possible for two filter instances to use the same
|
||||
// type (e.g., if there are two instantiations of the same filter).
|
||||
class Blackboard : public RefCounted<Blackboard> { |
||||
public: |
||||
// All entries must derive from this type.
|
||||
// They must also have a static method with the following signature:
|
||||
// static UniqueTypeName Type();
|
||||
class Entry : public RefCounted<Entry> {}; |
||||
|
||||
// Returns an entry for a particular type and name, or null if not present.
|
||||
template <typename T> |
||||
RefCountedPtr<T> Get(const std::string& key) const { |
||||
return Get(T::Type(), key).template TakeAsSubclass<T>(); |
||||
} |
||||
|
||||
// Sets an entry for a particular type and name.
|
||||
template <typename T> |
||||
void Set(const std::string& key, RefCountedPtr<T> entry) { |
||||
Set(T::Type(), key, std::move(entry)); |
||||
} |
||||
|
||||
private: |
||||
RefCountedPtr<Entry> Get(UniqueTypeName type, const std::string& key) const; |
||||
void Set(UniqueTypeName type, const std::string& key, |
||||
RefCountedPtr<Entry> entry); |
||||
|
||||
absl::flat_hash_map<std::pair<UniqueTypeName, std::string>, |
||||
RefCountedPtr<Entry>> |
||||
map_; |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_FILTER_BLACKBOARD_H
|
@ -0,0 +1,66 @@ |
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/filter/blackboard.h" |
||||
|
||||
#include "gmock/gmock.h" |
||||
#include "gtest/gtest.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace { |
||||
|
||||
class FooEntry : public Blackboard::Entry { |
||||
public: |
||||
static UniqueTypeName Type() { |
||||
static UniqueTypeName::Factory kFactory("FooEntry"); |
||||
return kFactory.Create(); |
||||
} |
||||
}; |
||||
|
||||
class BarEntry : public Blackboard::Entry { |
||||
public: |
||||
static UniqueTypeName Type() { |
||||
static UniqueTypeName::Factory kFactory("BarEntry"); |
||||
return kFactory.Create(); |
||||
} |
||||
}; |
||||
|
||||
TEST(Blackboard, Basic) { |
||||
Blackboard blackboard; |
||||
// No entry for type FooEntry key "foo".
|
||||
EXPECT_EQ(blackboard.Get<FooEntry>("a"), nullptr); |
||||
// Set entry for type FooEntry key "foo".
|
||||
auto foo_entry = MakeRefCounted<FooEntry>(); |
||||
blackboard.Set("a", foo_entry); |
||||
// Get the entry we just added.
|
||||
EXPECT_EQ(blackboard.Get<FooEntry>("a"), foo_entry); |
||||
// A different key for the same type is still unset.
|
||||
EXPECT_EQ(blackboard.Get<FooEntry>("b"), nullptr); |
||||
// The same key for a different type is still unset.
|
||||
EXPECT_EQ(blackboard.Get<BarEntry>("a"), nullptr); |
||||
// Set entry for type BarEntry key "foo".
|
||||
auto bar_entry = MakeRefCounted<BarEntry>(); |
||||
blackboard.Set("a", bar_entry); |
||||
EXPECT_EQ(blackboard.Get<BarEntry>("a"), bar_entry); |
||||
// This should not have replaced the same key for FooEntry.
|
||||
EXPECT_EQ(blackboard.Get<FooEntry>("a"), foo_entry); |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue