Skip to content

Commit 2d938b9

Browse files
trentmrogercoll
andauthored
[extension/apmconfig] save RemoteConfigStatus.LastRemoteConfigHash regardless of status (#609)
* [extension/apmconfig] save RemoteConfigStatus.LastRemoteConfigHash regardless of status Before this change the OpAMP server would only store the LastRemoteConfigHash provided in an AgentToServer message if the RemoteConfigStatus.Status was "APPLIED". An agent may want to (a) acknowledge that a particular config was received (via LastRemoteConfigHash) *and* (b) provide some other status (APPLYING or FAILED). In my particular case, for EDOT Node.js, I want to be able to support the case where the server might be sending new config names that an older EDOT Node.js might not know about. My RemoteConfigStatus in this case is: LastRemoteConfigHash: ... Status=FAILED ErrorMessage="there were issues applying remote config: config name 'some_new_var' is unsupported" The downside of the current behaviour is that the server will ignore the provided LastRemoteConfigHash and continue to re-send the same remote config in every ServerToAgent. Re-sending is not going to fix the issue the agent had with applying the config. My interpretation of the OpAMP spec and proto is that the OpAMP server should use *only* the LastRemoteConfigHash field for determining if RemoteConfig should be sent. The proto says: // The hash of the remote config that was last received by this Agent in the // AgentRemoteConfig.config_hash field. // The Server SHOULD compare this hash with the config hash // it has for the Agent and if the hashes are different the Server MUST include // the remote_config field in the response in the ServerToAgent message. * fix test case * ensure we save RemoteConfigStatus before a possible early return * add a test case for the RemoteConfigStatuses_FAILED case --------- Co-authored-by: Roger Coll <[email protected]>
1 parent eb327f9 commit 2d938b9

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

extension/apmconfigextension/opamp_callbacks.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ func (rc *remoteConfigCallbacks) onMessage(ctx context.Context, conn types.Conne
119119
rc.logger.Warn("unexpected type in agentState cache", agentUidField)
120120
return rc.serverError("internal error: invalid agent state", &serverToAgent)
121121
}
122+
remoteConfigStatus := message.GetRemoteConfigStatus()
123+
if remoteConfigStatus != nil {
124+
agent.lastConfigHash = remoteConfigStatus.GetLastRemoteConfigHash()
125+
rc.logger.Info("Remote config status", agentUidField, zap.String("lastRemoteConfigHash", hex.EncodeToString(agent.lastConfigHash)), zap.String("status", remoteConfigStatus.GetStatus().String()), zap.String("errorMessage", remoteConfigStatus.ErrorMessage))
126+
rc.agentState.Store(agentUid, agent)
127+
}
122128

123129
remoteConfig, err := rc.configClient.RemoteConfig(ctx, agent.agentUid, agent.identifyingAttributes)
124130
if err != nil {
@@ -132,11 +138,7 @@ func (rc *remoteConfigCallbacks) onMessage(ctx context.Context, conn types.Conne
132138
return &serverToAgent
133139
}
134140

135-
if message.GetRemoteConfigStatus() != nil && message.GetRemoteConfigStatus().Status == protobufs.RemoteConfigStatuses_RemoteConfigStatuses_APPLIED && bytes.Equal(remoteConfig.ConfigHash, message.RemoteConfigStatus.GetLastRemoteConfigHash()) {
136-
rc.logger.Info("Remote config applied", zap.String("hash", hex.EncodeToString(remoteConfig.ConfigHash)), agentUidField)
137-
agent.lastConfigHash = message.GetRemoteConfigStatus().GetLastRemoteConfigHash()
138-
rc.agentState.Store(agentUid, agent)
139-
} else if !bytes.Equal(agent.lastConfigHash, remoteConfig.ConfigHash) {
141+
if !bytes.Equal(agent.lastConfigHash, remoteConfig.ConfigHash) {
140142
rc.logger.Info("Sending new remote configuration", agentUidField, zap.String("hash", hex.EncodeToString(remoteConfig.ConfigHash)))
141143
serverToAgent.RemoteConfig = remoteConfig
142144
}

extension/apmconfigextension/opamp_callbacks_test.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,39 @@ func TestOnMessage(t *testing.T) {
177177
expectedServerToAgent: &protobufs.ServerToAgent{
178178
InstanceUid: []byte("test"),
179179
Capabilities: uint64(protobufs.ServerCapabilities_ServerCapabilities_OffersRemoteConfig),
180-
RemoteConfig: &protobufs.AgentRemoteConfig{
181-
ConfigHash: []byte("abcd"),
182-
Config: &protobufs.AgentConfigMap{
183-
ConfigMap: map[string]*protobufs.AgentConfigFile{
184-
"elastic": {
185-
Body: []byte(`{"test":"aaa"}`),
186-
ContentType: "application/json",
187-
},
180+
},
181+
},
182+
},
183+
callbacks: newRemoteConfigCallbacks(&remoteConfigMock{
184+
remoteConfigFn: func(context.Context, apmconfig.InstanceUid, apmconfig.IdentifyingAttributes) (*protobufs.AgentRemoteConfig, error) {
185+
return &protobufs.AgentRemoteConfig{
186+
ConfigHash: []byte("abcd"),
187+
Config: &protobufs.AgentConfigMap{
188+
ConfigMap: map[string]*protobufs.AgentConfigFile{
189+
"elastic": {
190+
ContentType: "application/json",
191+
Body: []byte(`{"test":"aaa"}`),
188192
},
189193
},
190194
},
195+
}, nil
196+
},
197+
}, zap.NewNop()),
198+
},
199+
"agent failed to apply remote config": {
200+
opampMessages: []inOutOpamp{
201+
{
202+
agentToServer: &protobufs.AgentToServer{
203+
InstanceUid: []byte("test"),
204+
RemoteConfigStatus: &protobufs.RemoteConfigStatus{
205+
LastRemoteConfigHash: []byte("abcd"),
206+
Status: protobufs.RemoteConfigStatuses_RemoteConfigStatuses_FAILED,
207+
ErrorMessage: "oh noes!",
208+
},
209+
},
210+
expectedServerToAgent: &protobufs.ServerToAgent{
211+
InstanceUid: []byte("test"),
212+
Capabilities: uint64(protobufs.ServerCapabilities_ServerCapabilities_OffersRemoteConfig),
191213
},
192214
},
193215
},

0 commit comments

Comments
 (0)