// Copyright 2018 Envoyproxy 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. package cache import ( "github.com/gogo/protobuf/proto" "github.com/envoyproxy/go-control-plane/envoy/api/v2" hcm "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" "github.com/envoyproxy/go-control-plane/pkg/util" ) // Resource is the base interface for the xDS payload. type Resource interface { proto.Message Equal(interface{}) bool } // Resource types in xDS v2. const ( typePrefix = "type.googleapis.com/envoy.api.v2." EndpointType = typePrefix + "ClusterLoadAssignment" ClusterType = typePrefix + "Cluster" RouteType = typePrefix + "RouteConfiguration" ListenerType = typePrefix + "Listener" // AnyType is used only by ADS AnyType = "" ) var ( // ResponseTypes are supported response types. ResponseTypes = []string{ EndpointType, ClusterType, RouteType, ListenerType, } ) // GetResourceName returns the resource name for a valid xDS response type. func GetResourceName(res Resource) string { switch v := res.(type) { case *v2.ClusterLoadAssignment: return v.GetClusterName() case *v2.Cluster: return v.GetName() case *v2.RouteConfiguration: return v.GetName() case *v2.Listener: return v.GetName() default: return "" } } // GetResourceReferences returns the names for dependent resources (EDS cluster // names for CDS, RDS routes names for LDS). func GetResourceReferences(resources map[string]Resource) map[string]bool { out := make(map[string]bool) for _, res := range resources { if res == nil { continue } switch v := res.(type) { case *v2.ClusterLoadAssignment: // no dependencies case *v2.Cluster: // for EDS type, use cluster name or ServiceName override if v.Type == v2.Cluster_EDS { if v.EdsClusterConfig != nil && v.EdsClusterConfig.ServiceName != "" { out[v.EdsClusterConfig.ServiceName] = true } else { out[v.Name] = true } } case *v2.RouteConfiguration: // References to clusters in both routes (and listeners) are not included // in the result, because the clusters are retrieved in bulk currently, // and not by name. case *v2.Listener: // extract route configuration names from HTTP connection manager for _, chain := range v.FilterChains { for _, filter := range chain.Filters { if filter.Name != util.HTTPConnectionManager { continue } config := &hcm.HttpConnectionManager{} if util.StructToMessage(filter.Config, config) == nil && config != nil { if rds, ok := config.RouteSpecifier.(*hcm.HttpConnectionManager_Rds); ok && rds != nil && rds.Rds != nil { out[rds.Rds.RouteConfigName] = true } } } } } } return out }