newLookupFunction returns the implementation of the chart `lookup` template function, dispatching across COSI resource kinds and emitting a deterministic error envelope on miss. nolint:funlen // closure over ctx/c plus a single linear dispatch over resource kinds wrapped in a retry-with-fail-fast l
(ctx context.Context, c *client.Client, commandName string, endpoints []string)
| 2123 | // |
| 2124 | //nolint:funlen // closure over ctx/c plus a single linear dispatch over resource kinds wrapped in a retry-with-fail-fast loop; extracting helpers would either thread (ctx, c) through every signature or hoist the closure body to package level. |
| 2125 | func newLookupFunction(ctx context.Context, c *client.Client, commandName string, endpoints []string) func(resource string, namespace string, id string) (map[string]any, error) { |
| 2126 | return func(kind string, namespace string, docID string) (map[string]any, error) { |
| 2127 | var multiErr *multierror.Error |
| 2128 | |
| 2129 | var resources []map[string]any |
| 2130 | |
| 2131 | // Signature is fixed by helpers.ForEachResource; the callback |
| 2132 | // always returns nil because per-item errors are accumulated |
| 2133 | // into multiErr / passed through for retry classification. |
| 2134 | //nolint:unparam // callback shape fixed by helpers.ForEachResource API |
| 2135 | callbackResource := func(_ context.Context, _ string, r resource.Resource, callError error) error { |
| 2136 | if callError != nil { |
| 2137 | // Ignore NotFound and PermissionDenied errors - resource doesn't exist or is not accessible |
| 2138 | errCode := status.Code(callError) |
| 2139 | |
| 2140 | errStr := callError.Error() |
| 2141 | if errCode == codes.NotFound || errCode == codes.PermissionDenied || |
| 2142 | strings.Contains(errStr, "code = NotFound") || strings.Contains(errStr, "code = PermissionDenied") { |
| 2143 | return nil |
| 2144 | } |
| 2145 | |
| 2146 | multiErr = multierror.Append(multiErr, callError) |
| 2147 | |
| 2148 | return nil |
| 2149 | } |
| 2150 | |
| 2151 | res, err := extractResourceData(r) |
| 2152 | if err != nil { |
| 2153 | multiErr = multierror.Append(multiErr, errors.Wrapf(err, "resource %s/%s", r.Metadata().Type(), r.Metadata().ID())) |
| 2154 | |
| 2155 | return nil |
| 2156 | } |
| 2157 | |
| 2158 | resources = append(resources, res) |
| 2159 | |
| 2160 | return nil |
| 2161 | } |
| 2162 | callbackRD := func(_ *meta.ResourceDefinition) error { |
| 2163 | return nil |
| 2164 | } |
| 2165 | |
| 2166 | // Retry transient connectivity failures up to defaultMaxAttempts |
| 2167 | // times; TLS handshake / authn / resource / unknown classes |
| 2168 | // fail fast — see retryWithFailFast docs. The closure resets |
| 2169 | // multiErr and resources at the top of each attempt so a |
| 2170 | // half-collected partial result from a failed attempt does not |
| 2171 | // leak into the next one. |
| 2172 | // |
| 2173 | // helpers.ForEachResource routes per-node dial failures (the |
| 2174 | // dominant transient class — a single node briefly partitioned |
| 2175 | // from the rest of a multi-node lookup) through callbackResource |
| 2176 | // as callError, where they land in multiErr and ForEachResource |
| 2177 | // itself returns nil. firstLookupError surfaces those to the |
| 2178 | // retry predicate so the brief-partition case is actually |
| 2179 | // retried, not silently wrapped on the first attempt. |
| 2180 | // |
| 2181 | // shouldRetry adds a partial-success fast-path: when at least |
| 2182 | // one node responded with data this attempt, retrying would |
no test coverage detected