mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-24 23:59:08 +02:00
[management] Return agent-network settings defaults before bootstrap
Settings endpoints elsewhere in the API always answer with a JSON object: account settings rows are created with the account and DNS settings live on it with zero-value defaults. Agent-network settings deviated because the row is created lazily at bootstrap (cluster is a deployment choice and the subdomain must be generated uniquely per cluster), and GetSettings passed the store's not-found straight through to the wire. The manager now synthesises the defaults on read when no row exists yet, without persisting: log collection on with the default retention, and an empty cluster, subdomain and endpoint as the not-bootstrapped signal. The timestamps stay off the wire until a row is written. Bootstrap persists the same defaults, so the pre-bootstrap view and the freshly bootstrapped row agree.
This commit is contained in:
@@ -77,9 +77,9 @@ func (a *AgentNetworkAPI) CreateProvider(ctx context.Context, request api.PostAp
|
||||
return &ret, err
|
||||
}
|
||||
|
||||
// UpdateProvider updates an Agent Network provider. Omitted optional fields
|
||||
// (api_key, models, extra_values, toggles, identity headers) keep their
|
||||
// stored values.
|
||||
// UpdateProvider updates an Agent Network provider. The request replaces the
|
||||
// provider's mutable state; only an omitted api_key keeps the stored key
|
||||
// (secrets are never required to round-trip).
|
||||
func (a *AgentNetworkAPI) UpdateProvider(ctx context.Context, providerID string, request api.PutApiAgentNetworkProvidersProviderIdJSONRequestBody) (*api.AgentNetworkProvider, error) {
|
||||
requestBytes, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
@@ -330,13 +330,13 @@ func (a *AgentNetworkAPI) DeleteBudgetRule(ctx context.Context, ruleID string) e
|
||||
}
|
||||
|
||||
// GetSettings gets the account's Agent Network gateway settings (cluster,
|
||||
// subdomain, endpoint, collection toggles). Returns an APIError with
|
||||
// StatusCode 404 (matchable via IsNotFound) when the account has not been
|
||||
// bootstrapped yet — bootstrap via UpdateSettings with a cluster, or by
|
||||
// creating the first provider with bootstrap_cluster set. Management servers
|
||||
// prior to the 404 contract answered 200 with a JSON null body in that case;
|
||||
// that legacy shape is translated to the same 404 APIError here so callers
|
||||
// only ever branch on IsNotFound.
|
||||
// subdomain, endpoint, collection toggles). An account that has not been
|
||||
// bootstrapped yet — via UpdateSettings with a cluster, or by creating the
|
||||
// first provider with bootstrap_cluster set — reads as the defaults with an
|
||||
// empty Cluster, Subdomain and Endpoint. Management servers prior to that
|
||||
// contract answered 200 with a JSON null body instead; that legacy shape is
|
||||
// translated to an APIError matchable via IsNotFound rather than fabricating
|
||||
// defaults the server never stated.
|
||||
func (a *AgentNetworkAPI) GetSettings(ctx context.Context) (*api.AgentNetworkSettings, error) {
|
||||
resp, err := a.c.NewRequest(ctx, "GET", "/api/agent-network/settings", nil, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -404,24 +404,45 @@ func TestAgentNetwork_GetSettings_200(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAgentNetwork_GetSettings_404(t *testing.T) {
|
||||
// TestAgentNetwork_GetSettings_UnbootstrappedDefaults pins the settings-read
|
||||
// contract: an unbootstrapped account answers 200 with the defaults and empty
|
||||
// cluster/subdomain/endpoint, which the client passes through untouched.
|
||||
func TestAgentNetwork_GetSettings_UnbootstrappedDefaults(t *testing.T) {
|
||||
withMockClient(func(c *rest.Client, mux *http.ServeMux) {
|
||||
mux.HandleFunc("/api/agent-network/settings", func(w http.ResponseWriter, r *http.Request) {
|
||||
retBytes, _ := json.Marshal(util.ErrorResponse{Message: "agent network settings not found", Code: 404})
|
||||
w.WriteHeader(404)
|
||||
retBytes, _ := json.Marshal(api.AgentNetworkSettings{
|
||||
EnableLogCollection: true,
|
||||
AccessLogRetentionDays: ptr(30),
|
||||
})
|
||||
_, err := w.Write(retBytes)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
ret, err := c.AgentNetwork.GetSettings(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, ret.Endpoint, "empty endpoint is the not-bootstrapped signal")
|
||||
assert.True(t, ret.EnableLogCollection, "defaults must pass through")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAgentNetwork_GetSettings_Err(t *testing.T) {
|
||||
withMockClient(func(c *rest.Client, mux *http.ServeMux) {
|
||||
mux.HandleFunc("/api/agent-network/settings", func(w http.ResponseWriter, r *http.Request) {
|
||||
retBytes, _ := json.Marshal(util.ErrorResponse{Message: "no", Code: 403})
|
||||
w.WriteHeader(403)
|
||||
_, err := w.Write(retBytes)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
_, err := c.AgentNetwork.GetSettings(context.Background())
|
||||
require.Error(t, err)
|
||||
assert.True(t, rest.IsNotFound(err), "unbootstrapped settings must be matchable via IsNotFound")
|
||||
assert.Equal(t, "no", err.Error())
|
||||
})
|
||||
}
|
||||
|
||||
// TestAgentNetwork_GetSettings_LegacyNullBody pins the compatibility shim for
|
||||
// management servers that answered 200 with a JSON null body before the 404
|
||||
// contract: the client must translate that shape into the same IsNotFound
|
||||
// error instead of returning a bogus zero-valued settings object.
|
||||
// management servers that answered 200 with a JSON null body before the
|
||||
// defaults contract: the client translates that shape into an IsNotFound
|
||||
// error instead of returning a bogus zero-valued settings object or
|
||||
// fabricating defaults the server never stated.
|
||||
func TestAgentNetwork_GetSettings_LegacyNullBody(t *testing.T) {
|
||||
withMockClient(func(c *rest.Client, mux *http.ServeMux) {
|
||||
mux.HandleFunc("/api/agent-network/settings", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user