1/*
2 *
3 * Copyright 2021 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package client
20
21import anypb "github.com/golang/protobuf/ptypes/any"
22
23// UpdateWithMD contains the raw message of the update and the metadata,
24// including version, raw message, timestamp.
25//
26// This is to be used for config dump and CSDS, not directly by users (like
27// resolvers/balancers).
28type UpdateWithMD struct {
29	MD  UpdateMetadata
30	Raw *anypb.Any
31}
32
33func rawFromCache(s string, cache interface{}) *anypb.Any {
34	switch c := cache.(type) {
35	case map[string]ListenerUpdate:
36		v, ok := c[s]
37		if !ok {
38			return nil
39		}
40		return v.Raw
41	case map[string]RouteConfigUpdate:
42		v, ok := c[s]
43		if !ok {
44			return nil
45		}
46		return v.Raw
47	case map[string]ClusterUpdate:
48		v, ok := c[s]
49		if !ok {
50			return nil
51		}
52		return v.Raw
53	case map[string]EndpointsUpdate:
54		v, ok := c[s]
55		if !ok {
56			return nil
57		}
58		return v.Raw
59	default:
60		return nil
61	}
62}
63
64func (c *clientImpl) dump(t ResourceType) (string, map[string]UpdateWithMD) {
65	c.mu.Lock()
66	defer c.mu.Unlock()
67
68	var (
69		version string
70		md      map[string]UpdateMetadata
71		cache   interface{}
72	)
73	switch t {
74	case ListenerResource:
75		version = c.ldsVersion
76		md = c.ldsMD
77		cache = c.ldsCache
78	case RouteConfigResource:
79		version = c.rdsVersion
80		md = c.rdsMD
81		cache = c.rdsCache
82	case ClusterResource:
83		version = c.cdsVersion
84		md = c.cdsMD
85		cache = c.cdsCache
86	case EndpointsResource:
87		version = c.edsVersion
88		md = c.edsMD
89		cache = c.edsCache
90	default:
91		c.logger.Errorf("dumping resource of unknown type: %v", t)
92		return "", nil
93	}
94
95	ret := make(map[string]UpdateWithMD, len(md))
96	for s, md := range md {
97		ret[s] = UpdateWithMD{
98			MD:  md,
99			Raw: rawFromCache(s, cache),
100		}
101	}
102	return version, ret
103}
104
105// DumpLDS returns the status and contents of LDS.
106func (c *clientImpl) DumpLDS() (string, map[string]UpdateWithMD) {
107	return c.dump(ListenerResource)
108}
109
110// DumpRDS returns the status and contents of RDS.
111func (c *clientImpl) DumpRDS() (string, map[string]UpdateWithMD) {
112	return c.dump(RouteConfigResource)
113}
114
115// DumpCDS returns the status and contents of CDS.
116func (c *clientImpl) DumpCDS() (string, map[string]UpdateWithMD) {
117	return c.dump(ClusterResource)
118}
119
120// DumpEDS returns the status and contents of EDS.
121func (c *clientImpl) DumpEDS() (string, map[string]UpdateWithMD) {
122	return c.dump(EndpointsResource)
123}
124