@@ -31,6 +31,12 @@ type Target struct {
3131 // appears in spec.Targets. When spec.Targets is empty (no explicit
3232 // target filtering), this field is false for all targets.
3333 SpecDefined bool `json:"specDefined,omitempty"`
34+
35+ // Hidden indicates that this route should not appear in the target
36+ // list but is still dispatchable. This is used for routes like bare
37+ // distro names (e.g. "mariner2") that act as aliases for a default
38+ // sub-route (e.g. "mariner2/container").
39+ Hidden bool `json:"hidden,omitempty"`
3440}
3541
3642// TargetList is the dalec-extended target list response.
@@ -54,9 +60,6 @@ type Route struct {
5460// It replaces the hierarchical BuildMux with a simpler dispatch model.
5561type Router struct {
5662 routes map [string ]Route
57-
58- // cached spec so we don't have to load it every time its needed
59- spec * dalec.Spec
6063}
6164
6265// Add registers a route. If a route with the same FullPath already exists
@@ -105,11 +108,6 @@ func (r *Router) Handle(ctx context.Context, client gwclient.Client) (_ *gwclien
105108 if retErr != nil {
106109 if _ , ok := opts [keyTopLevelTarget ]; ! ok {
107110 retErr = errors .Wrapf (retErr , "error handling requested build target %q" , target )
108-
109- spec , _ := r .loadSpec (ctx , client )
110- if spec != nil && spec .Name != "" {
111- retErr = errors .Wrapf (retErr , "spec: %s" , spec .Name )
112- }
113111 }
114112 }
115113 }()
@@ -201,17 +199,9 @@ func (r *Router) describe() (*gwclient.Result, error) {
201199}
202200
203201// list returns the target list. All route metadata is available directly —
204- // no handler invocation needed. Targets are annotated with SpecDefined
205- // based on the loaded spec .
202+ // no handler invocation needed. SpecDefined is set by providers at
203+ // route registration time .
206204func (r * Router ) list (ctx context.Context , client gwclient.Client , target string ) (* gwclient.Result , error ) {
207- spec , err := r .loadSpec (ctx , client )
208- if err != nil {
209- bklog .G (ctx ).WithError (err ).Warn ("Could not load spec for target list annotation" )
210- // Continue without spec — targets just won't have SpecDefined set.
211- }
212-
213- hasSpecTargets := spec != nil && len (spec .Targets ) > 0
214-
215205 var ls TargetList
216206
217207 keys := maps .Keys (r .routes )
@@ -225,15 +215,12 @@ func (r *Router) list(ctx context.Context, client gwclient.Client, target string
225215 continue
226216 }
227217
228- dt := route .Info
229- if hasSpecTargets {
230- tlk := topLevelKey (key )
231- if _ , ok := spec .Targets [tlk ]; ok {
232- dt .SpecDefined = true
233- }
218+ // Hidden routes are dispatchable but excluded from the target list.
219+ if route .Info .Hidden {
220+ continue
234221 }
235222
236- ls .Targets = append (ls .Targets , dt )
223+ ls .Targets = append (ls .Targets , route . Info )
237224 }
238225
239226 return dalecTargetListToResult (ls )
@@ -320,32 +307,27 @@ func (r *Router) lookupTarget(ctx context.Context, target string) (matchedPath s
320307 return "" , nil , handlerNotFound (target , maps .Keys (r .routes ))
321308}
322309
323- func (r * Router ) loadSpec (ctx context.Context , client gwclient.Client ) (* dalec.Spec , error ) {
324- if r .spec != nil {
325- return r .spec , nil
310+ // topLevelKey returns the first path segment of a route path.
311+ // e.g. "azlinux3/container/depsonly" → "azlinux3"
312+ func topLevelKey (routePath string ) string {
313+ if i := strings .IndexByte (routePath , '/' ); i >= 0 {
314+ return routePath [:i ]
326315 }
316+ return routePath
317+ }
318+
319+ // LoadSpecFromClient loads a dalec spec from the gateway client's build
320+ // context. Build args are substituted with WithAllowAnyArg so that
321+ // unresolved args don't cause errors during route setup.
322+ func LoadSpecFromClient (ctx context.Context , client gwclient.Client ) (* dalec.Spec , error ) {
327323 dc , err := dockerui .NewClient (client )
328324 if err != nil {
329325 return nil , err
330326 }
331327
332- spec , err := LoadSpec (ctx , dc , nil , func (cfg * LoadConfig ) {
328+ return LoadSpec (ctx , dc , nil , func (cfg * LoadConfig ) {
333329 cfg .SubstituteOpts = append (cfg .SubstituteOpts , dalec .WithAllowAnyArg )
334330 })
335- if err != nil {
336- return nil , err
337- }
338- r .spec = spec
339- return spec , nil
340- }
341-
342- // topLevelKey returns the first path segment of a route path.
343- // e.g. "azlinux3/container/depsonly" → "azlinux3"
344- func topLevelKey (routePath string ) string {
345- if i := strings .IndexByte (routePath , '/' ); i >= 0 {
346- return routePath [:i ]
347- }
348- return routePath
349331}
350332
351333// WithTargetForwardingHandler registers a forwarding handler for each
@@ -355,7 +337,7 @@ func WithTargetForwardingHandler(ctx context.Context, client gwclient.Client, r
355337 if k := GetTargetKey (client ); k != "" {
356338 return fmt .Errorf ("target forwarding requested but target is already forwarded: this is a bug in the frontend for %q" , k )
357339 }
358- spec , err := r . loadSpec (ctx , client )
340+ spec , err := LoadSpecFromClient (ctx , client )
359341 if err != nil {
360342 return err
361343 }
0 commit comments