1// Copyright 2018 Istio Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package routing 16 17import ( 18 tpb "istio.io/api/mixer/adapter/model/v1beta1" 19 descriptor "istio.io/api/policy/v1beta1" 20 "istio.io/istio/mixer/pkg/adapter" 21 "istio.io/istio/mixer/pkg/attribute" 22 "istio.io/istio/mixer/pkg/lang/compiled" 23 "istio.io/istio/mixer/pkg/template" 24 "istio.io/pkg/log" 25) 26 27// Table is the main routing table. It is used to find the set of handlers that should be invoked, along with the 28// instance builders and match conditions. 29type Table struct { 30 31 // id of this table. This is based on the config snapshot id. IDs are unique within the life-span of a Mixer instance. 32 id int64 33 34 // namespaceTables grouped by variety. 35 // Note that CHECK_WITH_OUTPUT templates are placed into CHECK variety group. 36 entries map[tpb.TemplateVariety]*varietyTable 37 38 debugInfo *tableDebugInfo 39} 40 41// varietyTable contains destination sets for a given template variety. It contains a mapping from namespaces 42// to a flattened list of destinations. It also contains the defaultSet, which gets returned if no namespace-specific 43// destination entry is found. 44type varietyTable struct { 45 // destinations grouped by namespace. These contain destinations from the default namespace as well. 46 entries map[string]*NamespaceTable 47 48 // destinations for default namespace 49 defaultSet *NamespaceTable 50} 51 52// NamespaceTable contains a list of destinations and directives that should be targeted for a given namespace. 53type NamespaceTable struct { 54 entries []*Destination 55 directives []*DirectiveGroup 56} 57 58var emptyDestinations = &NamespaceTable{} 59 60// Destination contains a target handler, and instances to send, grouped by the conditional match that applies to them. 61type Destination struct { 62 // id of the entry. IDs are reused every time a table is recreated. Used for debugging. 63 id uint32 64 65 // Handler to invoke 66 Handler adapter.Handler 67 68 // HandlerName is the name of the handler. Used for monitoring/logging purposes. 69 HandlerName string 70 71 // AdapterName is the name of the adapter. Used for monitoring/logging purposes. 72 AdapterName string 73 74 // Template of the handler. 75 Template *TemplateInfo 76 77 // InstanceGroups that should be (conditionally) applied to the handler. 78 InstanceGroups []*InstanceGroup 79 80 // Maximum number of instances that can be created from this entry. 81 maxInstances int 82 83 // FriendlyName is the friendly name of this configured handler entry. Used for monitoring/logging purposes. 84 FriendlyName string 85} 86 87// DirectiveGroup is a group of route directive expressions with a condition. 88// Directive expressions reference destination action names. 89// Note that InstanceGroup organizes by handlers, rather than rules, which necessitates 90// a different grouping for directives. 91type DirectiveGroup struct { 92 Condition compiled.Expression 93 Operations []*HeaderOperation 94} 95 96// HeaderOperationType is an enumeration for the route directive header operation template type. 97type HeaderOperationType int 98 99// Request and response header operation types. 100const ( 101 RequestHeaderOperation HeaderOperationType = iota 102 ResponseHeaderOperation 103) 104 105// HeaderOperation is an intermediate form of a rule header operation. 106type HeaderOperation struct { 107 Type HeaderOperationType 108 HeaderName string 109 HeaderValue compiled.Expression 110 Operation descriptor.Rule_HeaderOperationTemplate_Operation 111} 112 113// NamedBuilder holds a builder function and the short name of the associated instance. 114type NamedBuilder struct { 115 InstanceShortName string 116 Builder template.InstanceBuilderFn 117 118 // ActionName is the action name in the rule, used to reference the output of the handler applied to the instance 119 ActionName string 120} 121 122// TemplateInfo is the common data that is needed from a template 123type TemplateInfo struct { 124 Name string 125 Variety tpb.TemplateVariety 126 DispatchReport template.DispatchReportFn 127 DispatchCheck template.DispatchCheckFn 128 DispatchQuota template.DispatchQuotaFn 129 DispatchGenAttrs template.DispatchGenerateAttributesFn 130} 131 132func buildTemplateInfo(info *template.Info) *TemplateInfo { 133 return &TemplateInfo{ 134 Name: info.Name, 135 Variety: info.Variety, 136 DispatchReport: info.DispatchReport, 137 DispatchCheck: info.DispatchCheck, 138 DispatchQuota: info.DispatchQuota, 139 DispatchGenAttrs: info.DispatchGenAttrs, 140 } 141} 142 143// InstanceGroup is a set of instances that needs to be sent to a handler, grouped by a condition expression. 144type InstanceGroup struct { 145 // id of the InstanceGroup. IDs are reused every time a table is recreated. Used for debugging. 146 id uint32 147 148 // Condition for applying this instance group. 149 Condition compiled.Expression 150 151 // Builders for the instances in this group for each instance that should be applied. 152 Builders []NamedBuilder 153 154 // Mappers for attribute-generating adapters that map output attributes into the main attribute set. 155 Mappers []template.OutputMapperFn 156} 157 158var emptyTable = &Table{id: -1} 159 160// Empty returns an empty routing table. 161func Empty() *Table { 162 return emptyTable 163} 164 165// ID of the table. Based on the Config Snapshot id. 166func (t *Table) ID() int64 { 167 return t.id 168} 169 170// GetDestinations returns the set of destinations (handlers) for the given template variety and for the given namespace. 171// CHECK_WITH_OUTPUT variety destinations are grouped together with CHECK variety destinations. 172func (t *Table) GetDestinations(variety tpb.TemplateVariety, namespace string) *NamespaceTable { 173 destinations, ok := t.entries[variety] 174 if !ok { 175 log.Debugf("No destinations found for variety: table='%d', variety='%d'", t.id, variety) 176 177 return emptyDestinations 178 } 179 180 destinationSet := destinations.entries[namespace] 181 if destinationSet == nil { 182 log.Debugf("no rules for namespace, using defaults: table='%d', variety='%d', ns='%s'", t.id, variety, namespace) 183 destinationSet = destinations.defaultSet 184 } 185 186 return destinationSet 187} 188 189// Count returns the number of entries contained. 190func (d *NamespaceTable) Count() int { 191 return len(d.entries) 192} 193 194// Entries in the table. 195func (d *NamespaceTable) Entries() []*Destination { 196 return d.entries 197} 198 199// Directives in the table 200func (d *NamespaceTable) Directives() []*DirectiveGroup { 201 return d.directives 202} 203 204// MaxInstances returns the maximum number of instances that can be built from this Destination. 205func (d *Destination) MaxInstances() int { 206 return d.maxInstances 207} 208 209// used during building to recalculate maxInstances, after a modification. 210func (d *Destination) recalculateMaxInstances() { 211 c := 0 212 for _, input := range d.InstanceGroups { 213 c += len(input.Builders) 214 } 215 216 d.maxInstances = c 217} 218 219// Matches returns true, if the instances from this input set should be used for the given attribute bag. 220func (i *InstanceGroup) Matches(bag attribute.Bag) bool { 221 if i.Condition == nil { 222 return true 223 } 224 225 matches, err := i.Condition.EvaluateBoolean(bag) 226 if err != nil { 227 log.Warnf("input set condition evaluation error: id='%d', error='%v'", i.id, err) 228 return false 229 } 230 231 return matches 232} 233