1
#include "source/common/config/metadata.h"
2

            
3
#include "envoy/config/core/v3/base.pb.h"
4
#include "envoy/type/metadata/v3/metadata.pb.h"
5

            
6
#include "source/common/protobuf/utility.h"
7

            
8
namespace Envoy {
9
namespace Config {
10

            
11
SINGLETON_MANAGER_REGISTRATION(const_metadata_shared_pool);
12

            
13
MetadataKey::MetadataKey(const envoy::type::metadata::v3::MetadataKey& metadata_key)
14
85
    : key_(metadata_key.key()) {
15
115
  for (const auto& seg : metadata_key.path()) {
16
110
    path_.push_back(seg.key());
17
110
  }
18
85
}
19

            
20
const Protobuf::Value& Metadata::metadataValue(const envoy::config::core::v3::Metadata* metadata,
21
90
                                               const MetadataKey& metadata_key) {
22
90
  return metadataValue(metadata, metadata_key.key_, metadata_key.path_);
23
90
}
24

            
25
const Protobuf::Value& Metadata::metadataValue(const envoy::config::core::v3::Metadata* metadata,
26
                                               const std::string& filter,
27
56363
                                               const std::vector<std::string>& path) {
28
56363
  if (!metadata) {
29
52624
    return Protobuf::Value::default_instance();
30
52624
  }
31
3739
  const auto filter_it = metadata->filter_metadata().find(filter);
32
3739
  if (filter_it == metadata->filter_metadata().end()) {
33
596
    return Protobuf::Value::default_instance();
34
596
  }
35
3143
  return structValue(filter_it->second, path);
36
3739
}
37

            
38
const Protobuf::Value& Metadata::structValue(const Protobuf::Struct& struct_value,
39
3170
                                             const std::vector<std::string>& path) {
40
3170
  const Protobuf::Struct* data_struct = &struct_value;
41
3170
  const Protobuf::Value* val = nullptr;
42
  // go through path to select sub entries
43
3801
  for (const auto& p : path) {
44
3801
    if (nullptr == data_struct) { // sub entry not found
45
1
      return Protobuf::Value::default_instance();
46
1
    }
47
3800
    const auto entry_it = data_struct->fields().find(p);
48
3800
    if (entry_it == data_struct->fields().end()) {
49
734
      return Protobuf::Value::default_instance();
50
734
    }
51
3066
    val = &(entry_it->second);
52
3066
    if (val->has_struct_value()) {
53
647
      data_struct = &(val->struct_value());
54
2428
    } else {
55
2419
      data_struct = nullptr;
56
2419
    }
57
3066
  }
58
2435
  if (nullptr == val) {
59
1
    return Protobuf::Value::default_instance();
60
1
  }
61
2434
  return *val;
62
2435
}
63

            
64
const Protobuf::Value& Metadata::metadataValue(const envoy::config::core::v3::Metadata* metadata,
65
53887
                                               const std::string& filter, const std::string& key) {
66
53887
  const std::vector<std::string> path{key};
67
53887
  return metadataValue(metadata, filter, path);
68
53887
}
69

            
70
Protobuf::Value& Metadata::mutableMetadataValue(envoy::config::core::v3::Metadata& metadata,
71
1006
                                                const std::string& filter, const std::string& key) {
72
1006
  return (*(*metadata.mutable_filter_metadata())[filter].mutable_fields())[key];
73
1006
}
74

            
75
bool Metadata::metadataLabelMatch(const LabelSet& label_set,
76
                                  const envoy::config::core::v3::Metadata* host_metadata,
77
216
                                  const std::string& filter_key, bool list_as_any) {
78
216
  if (!host_metadata) {
79
20
    return label_set.empty();
80
20
  }
81
196
  const auto filter_it = host_metadata->filter_metadata().find(filter_key);
82
196
  if (filter_it == host_metadata->filter_metadata().end()) {
83
6
    return label_set.empty();
84
6
  }
85
190
  const Protobuf::Struct& data_struct = filter_it->second;
86
190
  const auto& fields = data_struct.fields();
87
190
  for (const auto& kv : label_set) {
88
178
    const auto entry_it = fields.find(kv.first);
89
178
    if (entry_it == fields.end()) {
90
39
      return false;
91
39
    }
92

            
93
139
    if (list_as_any && entry_it->second.kind_case() == Protobuf::Value::kListValue) {
94
3
      bool any_match = false;
95
5
      for (const auto& v : entry_it->second.list_value().values()) {
96
5
        if (ValueUtil::equal(v, kv.second)) {
97
2
          any_match = true;
98
2
          break;
99
2
        }
100
5
      }
101
3
      if (!any_match) {
102
1
        return false;
103
1
      }
104
136
    } else if (!ValueUtil::equal(entry_it->second, kv.second)) {
105
56
      return false;
106
56
    }
107
139
  }
108
94
  return true;
109
190
}
110

            
111
ConstMetadataSharedPoolSharedPtr
112
18149
Metadata::getConstMetadataSharedPool(Singleton::Manager& manager, Event::Dispatcher& dispatcher) {
113
18149
  return manager.getTyped<SharedPool::ObjectSharedPool<const envoy::config::core::v3::Metadata,
114
18149
                                                       MessageUtil, MessageUtil>>(
115
18149
      SINGLETON_MANAGER_REGISTERED_NAME(const_metadata_shared_pool), [&dispatcher] {
116
11442
        return std::make_shared<SharedPool::ObjectSharedPool<
117
11442
            const envoy::config::core::v3::Metadata, MessageUtil, MessageUtil>>(dispatcher);
118
11442
      });
119
18149
}
120

            
121
} // namespace Config
122
} // namespace Envoy