Skip to content

Commit

Permalink
api-gateway: subscribe to bound-api-gateway only after receiving api-…
Browse files Browse the repository at this point in the history
…gateway (#18291)

* api-gateway: subscribe to bound-api-gateway only after receiving api-gateway

This fixes a race condition due to our dependency on having the listener(s) from the api-gateway config entry in order to fully and properly process the resources on the bound-api-gateway config entry.

* Apply suggestions from code review

* Add changelog entry
  • Loading branch information
nathancoleman authored Jul 26, 2023
1 parent e29ceab commit 5caa0ae
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .changelog/18291.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
api-gateway: fix race condition in proxy config generation when Consul is notified of the bound-api-gateway config entry before it is notified of the api-gateway config entry.
```
22 changes: 12 additions & 10 deletions agent/proxycfg/api_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ func (h *handlerAPIGateway) initialize(ctx context.Context) (ConfigSnapshot, err
return snap, err
}

// Watch the bound-api-gateway's config entry
err = h.subscribeToConfigEntry(ctx, structs.BoundAPIGateway, h.service, h.proxyID.EnterpriseMeta, boundGatewayConfigWatchID)
if err != nil {
return snap, err
}

snap.APIGateway.Listeners = make(map[string]structs.APIGatewayListener)
snap.APIGateway.BoundListeners = make(map[string]structs.BoundAPIGatewayListener)
snap.APIGateway.HTTPRoutes = watch.NewMap[structs.ResourceReference, *structs.HTTPRouteConfigEntry]()
Expand Down Expand Up @@ -143,10 +137,12 @@ func (h *handlerAPIGateway) handleRootCAUpdate(u UpdateEvent, snap *ConfigSnapsh
return nil
}

// handleGatewayConfigUpdate responds to changes in the watched config entry for a gateway.
// In particular, we want to make sure that we're subscribing to any attached resources such
// as routes and certificates. These additional subscriptions will enable us to update the
// config snapshot appropriately for any route or certificate changes.
// handleGatewayConfigUpdate responds to changes in the watched config entries for a gateway.
// Once the base api-gateway config entry has been seen, we store the list of listeners and
// then subscribe to the corresponding bound-api-gateway config entry. We use the bound-api-gateway
// config entry to subscribe to any attached resources, including routes and certificates.
// These additional subscriptions will enable us to update the config snapshot appropriately
// for any route or certificate changes.
func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u UpdateEvent, snap *ConfigSnapshot, correlationID string) error {
resp, ok := u.Result.(*structs.ConfigEntryResponse)
if !ok {
Expand Down Expand Up @@ -244,6 +240,12 @@ func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u Upd
}

snap.APIGateway.GatewayConfigLoaded = true

// Watch the corresponding bound-api-gateway config entry
err := h.subscribeToConfigEntry(ctx, structs.BoundAPIGateway, h.service, h.proxyID.EnterpriseMeta, boundGatewayConfigWatchID)
if err != nil {
return err
}
break
default:
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
Expand Down

0 comments on commit 5caa0ae

Please sign in to comment.