1package api 2 3import ( 4 "encoding/json" 5 "fmt" 6 "time" 7) 8 9// DiscoveryChain can be used to query the discovery-chain endpoints 10type DiscoveryChain struct { 11 c *Client 12} 13 14// DiscoveryChain returns a handle to the discovery-chain endpoints 15func (c *Client) DiscoveryChain() *DiscoveryChain { 16 return &DiscoveryChain{c} 17} 18 19func (d *DiscoveryChain) Get(name string, opts *DiscoveryChainOptions, q *QueryOptions) (*DiscoveryChainResponse, *QueryMeta, error) { 20 if name == "" { 21 return nil, nil, fmt.Errorf("Name parameter must not be empty") 22 } 23 24 method := "GET" 25 if opts != nil && opts.requiresPOST() { 26 method = "POST" 27 } 28 29 r := d.c.newRequest(method, fmt.Sprintf("/v1/discovery-chain/%s", name)) 30 r.setQueryOptions(q) 31 32 if opts != nil { 33 if opts.EvaluateInDatacenter != "" { 34 r.params.Set("compile-dc", opts.EvaluateInDatacenter) 35 } 36 } 37 38 if method == "POST" { 39 r.obj = opts 40 } 41 42 rtt, resp, err := requireOK(d.c.doRequest(r)) 43 if err != nil { 44 return nil, nil, err 45 } 46 defer closeResponseBody(resp) 47 48 qm := &QueryMeta{} 49 parseQueryMeta(resp, qm) 50 qm.RequestTime = rtt 51 52 var out DiscoveryChainResponse 53 54 if err := decodeBody(resp, &out); err != nil { 55 return nil, nil, err 56 } 57 58 return &out, qm, nil 59} 60 61type DiscoveryChainOptions struct { 62 EvaluateInDatacenter string `json:"-"` 63 64 // OverrideMeshGateway allows for the mesh gateway setting to be overridden 65 // for any resolver in the compiled chain. 66 OverrideMeshGateway MeshGatewayConfig `json:",omitempty"` 67 68 // OverrideProtocol allows for the final protocol for the chain to be 69 // altered. 70 // 71 // - If the chain ordinarily would be TCP and an L7 protocol is passed here 72 // the chain will not include Routers or Splitters. 73 // 74 // - If the chain ordinarily would be L7 and TCP is passed here the chain 75 // will not include Routers or Splitters. 76 OverrideProtocol string `json:",omitempty"` 77 78 // OverrideConnectTimeout allows for the ConnectTimeout setting to be 79 // overridden for any resolver in the compiled chain. 80 OverrideConnectTimeout time.Duration `json:",omitempty"` 81} 82 83func (o *DiscoveryChainOptions) requiresPOST() bool { 84 if o == nil { 85 return false 86 } 87 return o.OverrideMeshGateway.Mode != "" || 88 o.OverrideProtocol != "" || 89 o.OverrideConnectTimeout != 0 90} 91 92type DiscoveryChainResponse struct { 93 Chain *CompiledDiscoveryChain 94} 95 96type CompiledDiscoveryChain struct { 97 ServiceName string 98 Namespace string 99 Datacenter string 100 101 // CustomizationHash is a unique hash of any data that affects the 102 // compilation of the discovery chain other than config entries or the 103 // name/namespace/datacenter evaluation criteria. 104 // 105 // If set, this value should be used to prefix/suffix any generated load 106 // balancer data plane objects to avoid sharing customized and 107 // non-customized versions. 108 CustomizationHash string 109 110 // Protocol is the overall protocol shared by everything in the chain. 111 Protocol string 112 113 // StartNode is the first key into the Nodes map that should be followed 114 // when walking the discovery chain. 115 StartNode string 116 117 // Nodes contains all nodes available for traversal in the chain keyed by a 118 // unique name. You can walk this by starting with StartNode. 119 // 120 // NOTE: The names should be treated as opaque values and are only 121 // guaranteed to be consistent within a single compilation. 122 Nodes map[string]*DiscoveryGraphNode 123 124 // Targets is a list of all targets used in this chain. 125 // 126 // NOTE: The names should be treated as opaque values and are only 127 // guaranteed to be consistent within a single compilation. 128 Targets map[string]*DiscoveryTarget 129} 130 131const ( 132 DiscoveryGraphNodeTypeRouter = "router" 133 DiscoveryGraphNodeTypeSplitter = "splitter" 134 DiscoveryGraphNodeTypeResolver = "resolver" 135) 136 137// DiscoveryGraphNode is a single node in the compiled discovery chain. 138type DiscoveryGraphNode struct { 139 Type string 140 Name string // this is NOT necessarily a service 141 142 // fields for Type==router 143 Routes []*DiscoveryRoute 144 145 // fields for Type==splitter 146 Splits []*DiscoverySplit 147 148 // fields for Type==resolver 149 Resolver *DiscoveryResolver 150 151 // shared by Type==resolver || Type==splitter 152 LoadBalancer *LoadBalancer `json:",omitempty"` 153} 154 155// compiled form of ServiceRoute 156type DiscoveryRoute struct { 157 Definition *ServiceRoute 158 NextNode string 159} 160 161// compiled form of ServiceSplit 162type DiscoverySplit struct { 163 Weight float32 164 NextNode string 165} 166 167// compiled form of ServiceResolverConfigEntry 168type DiscoveryResolver struct { 169 Default bool 170 ConnectTimeout time.Duration 171 Target string 172 Failover *DiscoveryFailover 173} 174 175func (r *DiscoveryResolver) MarshalJSON() ([]byte, error) { 176 type Alias DiscoveryResolver 177 exported := &struct { 178 ConnectTimeout string `json:",omitempty"` 179 *Alias 180 }{ 181 ConnectTimeout: r.ConnectTimeout.String(), 182 Alias: (*Alias)(r), 183 } 184 if r.ConnectTimeout == 0 { 185 exported.ConnectTimeout = "" 186 } 187 188 return json.Marshal(exported) 189} 190 191func (r *DiscoveryResolver) UnmarshalJSON(data []byte) error { 192 type Alias DiscoveryResolver 193 aux := &struct { 194 ConnectTimeout string 195 *Alias 196 }{ 197 Alias: (*Alias)(r), 198 } 199 if err := json.Unmarshal(data, &aux); err != nil { 200 return err 201 } 202 var err error 203 if aux.ConnectTimeout != "" { 204 if r.ConnectTimeout, err = time.ParseDuration(aux.ConnectTimeout); err != nil { 205 return err 206 } 207 } 208 return nil 209} 210 211// compiled form of ServiceResolverFailover 212type DiscoveryFailover struct { 213 Targets []string 214} 215 216// DiscoveryTarget represents all of the inputs necessary to use a resolver 217// config entry to execute a catalog query to generate a list of service 218// instances during discovery. 219type DiscoveryTarget struct { 220 ID string 221 222 Service string 223 ServiceSubset string 224 Namespace string 225 Datacenter string 226 227 MeshGateway MeshGatewayConfig 228 Subset ServiceResolverSubset 229 External bool 230 SNI string 231 Name string 232} 233