diff --git a/data/config.db b/data/config.db index 62493c1..2d92fba 100644 --- a/data/config.db +++ b/data/config.db Binary files differ diff --git a/internal/api/types.go b/internal/api/types.go index efc45a3..d3ac75c 100644 --- a/internal/api/types.go +++ b/internal/api/types.go @@ -54,6 +54,7 @@ type AppendFilterChainRequest struct { ListenerName string `json:"listener_name"` YAML string `json:"yaml"` + Upsert bool `json:"upsert"` } // UpdateFilterChainRequest defines payload to append a filter chain to a given listener diff --git a/internal/api_handlers.go b/internal/api_handlers.go index f93157a..fe13508 100644 --- a/internal/api_handlers.go +++ b/internal/api_handlers.go @@ -311,7 +311,7 @@ http.Error(w, fmt.Sprintf("failed to load filter chain %v", err), http.StatusBadRequest) return } - if err := api.Manager.AppendFilterChainToListener(ctx, req.ListenerName, chain); err != nil { + if err := api.Manager.AppendFilterChainToListener(ctx, req.ListenerName, chain, req.Upsert); err != nil { http.Error(w, fmt.Sprintf("failed to append filter chain: %v", err), http.StatusInternalServerError) return } diff --git a/internal/pkg/snapshot/resource_crud.go b/internal/pkg/snapshot/resource_crud.go index 6d878b5..288857b 100644 --- a/internal/pkg/snapshot/resource_crud.go +++ b/internal/pkg/snapshot/resource_crud.go @@ -22,7 +22,7 @@ // AppendFilterChainToListener loads the current listener from the cache, appends the provided // FilterChain to its list of FilterChains, and updates the cache with the new snapshot. -func (sm *SnapshotManager) AppendFilterChainToListener(ctx context.Context, listenerName string, newFilterChain *listenerv3.FilterChain) error { +func (sm *SnapshotManager) AppendFilterChainToListener(ctx context.Context, listenerName string, newFilterChain *listenerv3.FilterChain, upsert bool) error { log := internallog.LogFromContext(ctx) // 1. Get the current Listener from the cache @@ -36,9 +36,25 @@ return fmt.Errorf("resource '%s' is not a Listener type", listenerName) } - // 2. Append the new FilterChain to the listener's list of filter chains. - listener.FilterChains = append(listener.FilterChains, newFilterChain) - log.Infof("Appended new filter chain (match: %v) to listener '%s'", newFilterChain.FilterChainMatch, listenerName) + replaced := false + for i, fc := range listener.FilterChains { + if fc.Name == newFilterChain.Name { + if !upsert { + return fmt.Errorf("filter chain with name '%s' already exists in listener '%s' and upsert is false", newFilterChain.Name, listenerName) + } + listener.FilterChains[i] = newFilterChain + replaced = true + log.Infof("Replaced new filter chain (match: %v) to listener '%s'", newFilterChain.FilterChainMatch, listenerName) + break + } + } + + if !replaced { + // 2. Append the new FilterChain to the listener's list of filter chains. + listener.FilterChains = append(listener.FilterChains, newFilterChain) + log.Infof("Appended new filter chain (match: %v) to listener '%s'", newFilterChain.FilterChainMatch, listenerName) + + } // 3. Create a new snapshot with the modified listener (rest of logic remains similar) snap, err := sm.Cache.GetSnapshot(sm.NodeID) diff --git a/static/global.js b/static/global.js index 4d57d2b..a46e4c5 100644 --- a/static/global.js +++ b/static/global.js @@ -272,7 +272,7 @@ export async function submitNewFilterChain() { const listenerName = document.getElementById('add-fc-listener-name').value; const yamlData = document.getElementById('add-fc-yaml-input').value.trim(); - + const upsertCheckbox = document.getElementById('add-filter-chain-upsert-flag'); if (!yamlData) { alert("Please paste the filter chain YAML configuration."); return; @@ -285,6 +285,10 @@ const payload = { listener_name: listenerName, yaml: yamlData }; + if (upsertCheckbox && upsertCheckbox.checked) { + payload.upsert = true; + } + try { const response = await fetch(`${API_BASE_URL}/append-filter-chain`, { method: 'POST', @@ -297,7 +301,7 @@ throw new Error(`HTTP Error ${response.status}: ${errorBody}`); } - alert(`Successfully appended new filter chain to '${listenerName}'.`); + alert(`Successfully update new filter chain to '${listenerName}'.`); document.getElementById('addFilterChainModal').style.display = 'none'; diff --git a/static/index.html b/static/index.html index e11bc15..168c8ad 100644 --- a/static/index.html +++ b/static/index.html @@ -23,9 +23,10 @@