Implement TextMarshaler for ContainerStatus #4135
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
ContainerStatus
currently does not implement encoding.TextMarshaler interface which causes it to be marshaled as integers (such as "1") instead of strings (such as "PULLED") in some cases that depend onTextMarshaler
interface. An example of such a case is whenContainerStatus
is a key in amap
. Due to this issue,TransitionDependenciesMap
type, which is a type alias formap[ContainerStatus]TransitionDependencySet
, is marshaled with integer keys as shown below.This behavior of json.Marshal function is documented.
It is problematic to marshal
ContainerStatus
as integers because when a new container state is introduced data marshaled by an older Agent version will be silently unmarshaled incorrectly by a newer Agent version. For example, an older Agent version would marshalContainerPulled
state as "1" but if a new state is introduced betweenContainerStatusNone
andContainerPulled
then a newer Agent version will unmarshal "1" as that new state. We will be introducing a new container state in an upcoming PR which is why this PR is needed first.To solve this issue, this PR implements encoding.TestMarshaler and its counterpart encoding.TestUnmarshaler interfaces for
ContainerStatus
type so that text marshaling ofContainerStatus
uses strings instead of integers.On the other hand, when unmarshaling JSON object keys, json.Unmarshal function gives preference to json.Unmarshaler interface over encoding.TextUnmarshaler.
For this reason, we need to make
ContainerStatus.UnmarshalJSON
method backwards-compatible with integer based marshaling ofContainerStatus
. This PR adds code inUnmarshalJSON
to handle integer toContainerStatus
mapping for old state files.Implementation details
MarshalText
method forContainerStatus
. The method has a value receiver as otherwise the method is not invoked forContainerStatus
values. The method is invoked for pointers toContainerStatus
too so both cases are covered. The method simply callsString()
method.UnmarshalText
method forContainerStatus
which unmarshalsContainerStatus
from its text form.MarshalJSON
method ofContainerStatus
to capture current integer toContainerStatus
mapping and use it unmarshalContainerStatus
from its old integer based marshaling. The mapping from integer toContainerStatus
does not need to be updated as we add new states as it is only for backwards compatibility with old Agent state files that won't ever have new states.TransitionDependenciesMap
type to ensure thatContainerStatus
keys are marshaled as strings now and unmarshaling from older formats works (for backward-compatibility).Forward compatibility
This change is not forward compatible (but it is backward compatible) with older Agent versions as Agent's state loading logic does not take into account the version of the persisted state. This is true for all changes made to state format and contents. If Agent is downgraded after running an Agent version with this change, then the downgraded version will not have any state transition dependencies loaded for any containers. Agent will still start-up and run.
The following error will show in the logs.
Testing
Performed the following manual test.
TransitionDependenciesMap
to ensure that task containers are started after the pause container reachesRUNNING
and the pause container is stopped after task containers reachSTOPPED
.The logs show that the new Agent parsed
as
and
as
which shows that "1" was unmarshaled as
ContainerPulled
and "5" was unmarshaled asContainerStopped
which is expected.This time Agent saw string based keys for
ContainerStatus
when parsing containers from the state file which means that the new Agent correctly marshaledContainerStatus
keys as strings instead of integers.After parsing both containers had the same value as before for
TransitionDependencySet
.New tests cover the changes: yes
Description for the changelog
Enhancement: Marshal ContainerStatus as strings instead of integers for JSON keys by implementing encoding.TextMarshaler.
Does this PR include breaking model changes? If so, Have you added transformation functions?
Licensing
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.