Skip to content

Commit 9c792e5

Browse files
n00bitaxHarness
authored and
Harness
committed
fix: [CDE-555]: allow mixed data types in lifecycle command object form. (#3169)
* fix: [CDE-555]: allow mixed data types in lifecycle command object form. * fix: [CDE-555]: allow mixed data types in lifecycle command object form. * fix: [CDE-555]: allow mixed data types in lifecycle command object form.
1 parent de91e0d commit 9c792e5

File tree

1 file changed

+53
-44
lines changed

1 file changed

+53
-44
lines changed

types/devcontainer_config.go

+53-44
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package types
1616

1717
import (
1818
"encoding/json"
19-
"errors"
19+
"fmt"
2020
"strings"
2121
)
2222

@@ -33,24 +33,21 @@ type DevcontainerConfig struct {
3333
RemoteUser string `json:"remoteUser,omitempty"`
3434
}
3535

36-
//nolint:tagliatelle
37-
type LifecycleCommand struct {
38-
CommandString string `json:"commandString,omitempty"`
39-
CommandArray []string `json:"commandArray,omitempty"`
40-
// Map to store commands by tags
41-
CommandMap map[string]string `json:"commandMap,omitempty"`
42-
CommandMapArray map[string][]string `json:"commandMapArray,omitempty"`
43-
Discriminator string `json:"-"` // Tracks the original type for proper re-marshaling
44-
}
45-
4636
// Constants for discriminator values.
4737
const (
48-
TypeString = "string"
49-
TypeArray = "array"
50-
TypeCommandMapString = "commandMap"
51-
TypeCommandMapArray = "commandMapArray"
38+
TypeString = "string"
39+
TypeArray = "array"
40+
TypeCommandMap = "commandMap"
5241
)
5342

43+
//nolint:tagliatelle
44+
type LifecycleCommand struct {
45+
CommandString string `json:"commandString,omitempty"`
46+
CommandArray []string `json:"commandArray,omitempty"`
47+
CommandMap map[string]any `json:"commandMap,omitempty"`
48+
Discriminator string `json:"-"` // Tracks the original type for proper re-marshaling
49+
}
50+
5451
func (lc *LifecycleCommand) UnmarshalJSON(data []byte) error {
5552
// Try to unmarshal as a single string
5653
var commandStr string
@@ -59,28 +56,43 @@ func (lc *LifecycleCommand) UnmarshalJSON(data []byte) error {
5956
lc.Discriminator = TypeString
6057
return nil
6158
}
59+
6260
// Try to unmarshal as an array of strings
6361
var commandArr []string
6462
if err := json.Unmarshal(data, &commandArr); err == nil {
6563
lc.CommandArray = commandArr
6664
lc.Discriminator = TypeArray
6765
return nil
6866
}
69-
// Try to unmarshal as a map of commands (tags to commands)
70-
var commandMap map[string]string
71-
if err := json.Unmarshal(data, &commandMap); err == nil {
72-
lc.CommandMap = commandMap
73-
lc.Discriminator = TypeCommandMapString
74-
return nil
75-
}
76-
// Try to unmarshal as a CommandMapArray
77-
var commandMapArray map[string][]string
78-
if err := json.Unmarshal(data, &commandMapArray); err == nil {
79-
lc.CommandMapArray = commandMapArray
80-
lc.Discriminator = TypeCommandMapArray
67+
68+
// Try to unmarshal as a map with mixed types
69+
var rawMap map[string]any
70+
if err := json.Unmarshal(data, &rawMap); err == nil {
71+
for key, value := range rawMap {
72+
switch v := value.(type) {
73+
case string:
74+
// Valid string value
75+
case []interface{}:
76+
// Convert []interface{} to []string
77+
var strArray []string
78+
for _, item := range v {
79+
if str, ok := item.(string); ok {
80+
strArray = append(strArray, str)
81+
} else {
82+
return fmt.Errorf("invalid format: array contains non-string value")
83+
}
84+
}
85+
rawMap[key] = strArray
86+
default:
87+
return fmt.Errorf("invalid format: map contains unsupported type")
88+
}
89+
}
90+
lc.CommandMap = rawMap
91+
lc.Discriminator = TypeCommandMap
8192
return nil
8293
}
83-
return errors.New("invalid format: must be string, []string, map[string]string, or map[string][]string")
94+
95+
return fmt.Errorf("invalid format: must be string, []string, or map[string]any")
8496
}
8597

8698
func (lc *LifecycleCommand) MarshalJSON() ([]byte, error) {
@@ -89,32 +101,29 @@ func (lc *LifecycleCommand) MarshalJSON() ([]byte, error) {
89101
return json.Marshal(lc.CommandString)
90102
case TypeArray:
91103
return json.Marshal(lc.CommandArray)
92-
case TypeCommandMapString:
104+
case TypeCommandMap:
93105
return json.Marshal(lc.CommandMap)
94-
case TypeCommandMapArray:
95-
return json.Marshal(lc.CommandMapArray)
96106
default:
97-
return nil, errors.New("unknown type for LifecycleCommand")
107+
return nil, fmt.Errorf("unknown type for LifecycleCommand")
98108
}
99109
}
100110

101111
// ToCommandArray converts the LifecycleCommand into a slice of full commands.
102112
func (lc *LifecycleCommand) ToCommandArray() []string {
103-
switch {
104-
case lc.CommandString != "":
113+
switch lc.Discriminator {
114+
case TypeString:
105115
return []string{lc.CommandString}
106-
case lc.CommandArray != nil:
116+
case TypeArray:
107117
return []string{strings.Join(lc.CommandArray, " ")}
108-
case lc.CommandMap != nil:
109-
var commands []string
110-
for _, command := range lc.CommandMap {
111-
commands = append(commands, command)
112-
}
113-
return commands
114-
case lc.CommandMapArray != nil:
118+
case TypeCommandMap:
115119
var commands []string
116-
for _, commandArray := range lc.CommandMapArray {
117-
commands = append(commands, strings.Join(commandArray, " "))
120+
for _, value := range lc.CommandMap {
121+
switch v := value.(type) {
122+
case string:
123+
commands = append(commands, v)
124+
case []string:
125+
commands = append(commands, strings.Join(v, " "))
126+
}
118127
}
119128
return commands
120129
default:

0 commit comments

Comments
 (0)