Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/config/metadata.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <memory>
4
#include <string>
5
6
#include "envoy/config/core/v3/base.pb.h"
7
#include "envoy/config/typed_metadata.h"
8
#include "envoy/event/dispatcher.h"
9
#include "envoy/registry/registry.h"
10
#include "envoy/singleton/manager.h"
11
#include "envoy/type/metadata/v3/metadata.pb.h"
12
13
#include "source/common/protobuf/protobuf.h"
14
#include "source/common/shared_pool/shared_pool.h"
15
16
#include "absl/container/node_hash_map.h"
17
18
namespace Envoy {
19
namespace Config {
20
21
using ConstMetadataSharedPoolSharedPtr =
22
    std::shared_ptr<SharedPool::ObjectSharedPool<const envoy::config::core::v3::Metadata,
23
                                                 MessageUtil, MessageUtil>>;
24
25
/**
26
 * MetadataKey presents the key name and path to retrieve value from metadata.
27
 */
28
struct MetadataKey {
29
  std::string key_;
30
  std::vector<std::string> path_;
31
32
  MetadataKey(const envoy::type::metadata::v3::MetadataKey& metadata_key);
33
};
34
35
/**
36
 * Config metadata helpers.
37
 */
38
class Metadata {
39
public:
40
  /**
41
   * Lookup value of a key for a given filter in Metadata.
42
   * @param metadata reference.
43
   * @param filter name.
44
   * @param key for filter metadata.
45
   * @return const ProtobufWkt::Value& value if found, empty if not found.
46
   */
47
  static const ProtobufWkt::Value& metadataValue(const envoy::config::core::v3::Metadata* metadata,
48
                                                 const std::string& filter, const std::string& key);
49
  /**
50
   * Lookup value by a multi-key path for a given filter in Metadata. If path is empty
51
   * will return the empty struct.
52
   * @param metadata reference.
53
   * @param filter name.
54
   * @param path multi-key path.
55
   * @return const ProtobufWkt::Value& value if found, empty if not found.
56
   */
57
  static const ProtobufWkt::Value& metadataValue(const envoy::config::core::v3::Metadata* metadata,
58
                                                 const std::string& filter,
59
                                                 const std::vector<std::string>& path);
60
  /**
61
   * Lookup the value by a metadata key from a Metadata.
62
   * @param metadata reference.
63
   * @param metadata_key with key name and path to retrieve the value.
64
   * @return const ProtobufWkt::Value& value if found, empty if not found.
65
   */
66
  static const ProtobufWkt::Value& metadataValue(const envoy::config::core::v3::Metadata* metadata,
67
                                                 const MetadataKey& metadata_key);
68
69
  /**
70
   * Obtain mutable reference to metadata value for a given filter and key.
71
   * @param metadata reference.
72
   * @param filter name.
73
   * @param key for filter metadata.
74
   * @return ProtobufWkt::Value&. A Value message is created if not found.
75
   */
76
  static ProtobufWkt::Value& mutableMetadataValue(envoy::config::core::v3::Metadata& metadata,
77
                                                  const std::string& filter,
78
                                                  const std::string& key);
79
80
  using LabelSet = std::vector<std::pair<std::string, ProtobufWkt::Value>>;
81
82
  /**
83
   * Returns whether a set of the labels match a particular host's metadata.
84
   * @param label_set the target label key/value pair set.
85
   * @param host_metadata a given host's metadata.
86
   * @param filter_key identifies the entry in the metadata entry for the match.
87
   * @param list_as_any if the metadata value entry is a list, and any one of
88
   * the element equals to the input label_set, it's considered as match.
89
   */
90
  static bool metadataLabelMatch(const LabelSet& label_set,
91
                                 const envoy::config::core::v3::Metadata* host_metadata,
92
                                 const std::string& filter_key, bool list_as_any);
93
  /**
94
   * Returns an ObjectSharedPool to store const Metadata
95
   * @param manager used to create singleton
96
   * @param dispatcher the dispatcher object reference to the thread that created the
97
   * ObjectSharedPool
98
   */
99
  static ConstMetadataSharedPoolSharedPtr getConstMetadataSharedPool(Singleton::Manager& manager,
100
                                                                     Event::Dispatcher& dispatcher);
101
};
102
103
template <typename factoryClass> class TypedMetadataImpl : public TypedMetadata {
104
public:
105
  static_assert(std::is_base_of<Config::TypedMetadataFactory, factoryClass>::value,
106
                "Factory type must be inherited from Envoy::Config::TypedMetadataFactory.");
107
30.5k
  TypedMetadataImpl(const envoy::config::core::v3::Metadata& metadata) { populateFrom(metadata); }
Envoy::Config::TypedMetadataImpl<Envoy::Router::HttpRouteTypedMetadataFactory>::TypedMetadataImpl(envoy::config::core::v3::Metadata const&)
Line
Count
Source
107
17.7k
  TypedMetadataImpl(const envoy::config::core::v3::Metadata& metadata) { populateFrom(metadata); }
Unexecuted instantiation: Envoy::Config::TypedMetadataImpl<Envoy::Upstream::ClusterTypedMetadataFactory>::TypedMetadataImpl(envoy::config::core::v3::Metadata const&)
Envoy::Config::TypedMetadataImpl<Envoy::Config::TypedMetadataFactory>::TypedMetadataImpl(envoy::config::core::v3::Metadata const&)
Line
Count
Source
107
118
  TypedMetadataImpl(const envoy::config::core::v3::Metadata& metadata) { populateFrom(metadata); }
Envoy::Config::TypedMetadataImpl<Envoy::Network::ListenerTypedMetadataFactory>::TypedMetadataImpl(envoy::config::core::v3::Metadata const&)
Line
Count
Source
107
12.7k
  TypedMetadataImpl(const envoy::config::core::v3::Metadata& metadata) { populateFrom(metadata); }
108
109
0
  const TypedMetadata::Object* getData(const std::string& key) const override {
110
0
    const auto& it = data_.find(key);
111
0
    return it == data_.end() ? nullptr : it->second.get();
112
0
  }
Unexecuted instantiation: Envoy::Config::TypedMetadataImpl<Envoy::Upstream::ClusterTypedMetadataFactory>::getData(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: Envoy::Config::TypedMetadataImpl<Envoy::Router::HttpRouteTypedMetadataFactory>::getData(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: Envoy::Config::TypedMetadataImpl<Envoy::Config::TypedMetadataFactory>::getData(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: Envoy::Config::TypedMetadataImpl<Envoy::Network::ListenerTypedMetadataFactory>::getData(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
113
114
protected:
115
  /* Attempt to run each of the registered factories for TypedMetadata, to
116
   * populate the data_ map.
117
   */
118
30.5k
  void populateFrom(const envoy::config::core::v3::Metadata& metadata) {
119
30.5k
    auto& data_by_key = metadata.filter_metadata();
120
30.5k
    auto& typed_data_by_key = metadata.typed_filter_metadata();
121
30.5k
    for (const auto& [factory_name, factory] :
122
30.5k
         Registry::FactoryRegistry<factoryClass>::factories()) {
123
0
      const auto& typed_meta_iter = typed_data_by_key.find(factory_name);
124
      // If the key exists in Any metadata, and parse() does not return nullptr,
125
      // populate data_.
126
0
      if (typed_meta_iter != typed_data_by_key.end()) {
127
0
        auto result = factory->parse(typed_meta_iter->second);
128
0
        if (result != nullptr) {
129
0
          data_[factory->name()] = std::move(result);
130
0
          continue;
131
0
        }
132
0
      }
133
      // Fall back cases to parsing Struct metadata and populate data_.
134
0
      const auto& meta_iter = data_by_key.find(factory_name);
135
0
      if (meta_iter != data_by_key.end()) {
136
0
        data_[factory->name()] = factory->parse(meta_iter->second);
137
0
      }
138
0
    }
139
30.5k
  }
Unexecuted instantiation: Envoy::Config::TypedMetadataImpl<Envoy::Upstream::ClusterTypedMetadataFactory>::populateFrom(envoy::config::core::v3::Metadata const&)
Envoy::Config::TypedMetadataImpl<Envoy::Router::HttpRouteTypedMetadataFactory>::populateFrom(envoy::config::core::v3::Metadata const&)
Line
Count
Source
118
17.7k
  void populateFrom(const envoy::config::core::v3::Metadata& metadata) {
119
17.7k
    auto& data_by_key = metadata.filter_metadata();
120
17.7k
    auto& typed_data_by_key = metadata.typed_filter_metadata();
121
17.7k
    for (const auto& [factory_name, factory] :
122
17.7k
         Registry::FactoryRegistry<factoryClass>::factories()) {
123
0
      const auto& typed_meta_iter = typed_data_by_key.find(factory_name);
124
      // If the key exists in Any metadata, and parse() does not return nullptr,
125
      // populate data_.
126
0
      if (typed_meta_iter != typed_data_by_key.end()) {
127
0
        auto result = factory->parse(typed_meta_iter->second);
128
0
        if (result != nullptr) {
129
0
          data_[factory->name()] = std::move(result);
130
0
          continue;
131
0
        }
132
0
      }
133
      // Fall back cases to parsing Struct metadata and populate data_.
134
0
      const auto& meta_iter = data_by_key.find(factory_name);
135
0
      if (meta_iter != data_by_key.end()) {
136
0
        data_[factory->name()] = factory->parse(meta_iter->second);
137
0
      }
138
0
    }
139
17.7k
  }
Envoy::Config::TypedMetadataImpl<Envoy::Config::TypedMetadataFactory>::populateFrom(envoy::config::core::v3::Metadata const&)
Line
Count
Source
118
118
  void populateFrom(const envoy::config::core::v3::Metadata& metadata) {
119
118
    auto& data_by_key = metadata.filter_metadata();
120
118
    auto& typed_data_by_key = metadata.typed_filter_metadata();
121
118
    for (const auto& [factory_name, factory] :
122
118
         Registry::FactoryRegistry<factoryClass>::factories()) {
123
0
      const auto& typed_meta_iter = typed_data_by_key.find(factory_name);
124
      // If the key exists in Any metadata, and parse() does not return nullptr,
125
      // populate data_.
126
0
      if (typed_meta_iter != typed_data_by_key.end()) {
127
0
        auto result = factory->parse(typed_meta_iter->second);
128
0
        if (result != nullptr) {
129
0
          data_[factory->name()] = std::move(result);
130
0
          continue;
131
0
        }
132
0
      }
133
      // Fall back cases to parsing Struct metadata and populate data_.
134
0
      const auto& meta_iter = data_by_key.find(factory_name);
135
0
      if (meta_iter != data_by_key.end()) {
136
0
        data_[factory->name()] = factory->parse(meta_iter->second);
137
0
      }
138
0
    }
139
118
  }
Envoy::Config::TypedMetadataImpl<Envoy::Network::ListenerTypedMetadataFactory>::populateFrom(envoy::config::core::v3::Metadata const&)
Line
Count
Source
118
12.7k
  void populateFrom(const envoy::config::core::v3::Metadata& metadata) {
119
12.7k
    auto& data_by_key = metadata.filter_metadata();
120
12.7k
    auto& typed_data_by_key = metadata.typed_filter_metadata();
121
12.7k
    for (const auto& [factory_name, factory] :
122
12.7k
         Registry::FactoryRegistry<factoryClass>::factories()) {
123
0
      const auto& typed_meta_iter = typed_data_by_key.find(factory_name);
124
      // If the key exists in Any metadata, and parse() does not return nullptr,
125
      // populate data_.
126
0
      if (typed_meta_iter != typed_data_by_key.end()) {
127
0
        auto result = factory->parse(typed_meta_iter->second);
128
0
        if (result != nullptr) {
129
0
          data_[factory->name()] = std::move(result);
130
0
          continue;
131
0
        }
132
0
      }
133
      // Fall back cases to parsing Struct metadata and populate data_.
134
0
      const auto& meta_iter = data_by_key.find(factory_name);
135
0
      if (meta_iter != data_by_key.end()) {
136
0
        data_[factory->name()] = factory->parse(meta_iter->second);
137
0
      }
138
0
    }
139
12.7k
  }
140
141
  absl::node_hash_map<std::string, std::unique_ptr<const TypedMetadata::Object>> data_;
142
};
143
144
// MetadataPack is struct that contains both the proto and typed metadata.
145
template <class FactoryClass> struct MetadataPack {
146
  MetadataPack(const envoy::config::core::v3::Metadata& metadata)
147
21.8k
      : proto_metadata_(metadata), typed_metadata_(proto_metadata_) {}
Envoy::Config::MetadataPack<Envoy::Router::HttpRouteTypedMetadataFactory>::MetadataPack(envoy::config::core::v3::Metadata const&)
Line
Count
Source
147
17.7k
      : proto_metadata_(metadata), typed_metadata_(proto_metadata_) {}
Envoy::Config::MetadataPack<Envoy::Network::ListenerTypedMetadataFactory>::MetadataPack(envoy::config::core::v3::Metadata const&)
Line
Count
Source
147
4.14k
      : proto_metadata_(metadata), typed_metadata_(proto_metadata_) {}
148
8.55k
  MetadataPack() : proto_metadata_(), typed_metadata_(proto_metadata_) {}
Unexecuted instantiation: Envoy::Config::MetadataPack<Envoy::Router::HttpRouteTypedMetadataFactory>::MetadataPack()
Envoy::Config::MetadataPack<Envoy::Network::ListenerTypedMetadataFactory>::MetadataPack()
Line
Count
Source
148
8.55k
  MetadataPack() : proto_metadata_(), typed_metadata_(proto_metadata_) {}
149
150
  const envoy::config::core::v3::Metadata proto_metadata_;
151
  const TypedMetadataImpl<FactoryClass> typed_metadata_;
152
};
153
154
template <class FactoryClass> using MetadataPackPtr = std::unique_ptr<MetadataPack<FactoryClass>>;
155
template <class FactoryClass>
156
using MetadataPackSharedPtr = std::shared_ptr<MetadataPack<FactoryClass>>;
157
158
} // namespace Config
159
} // namespace Envoy