@@ -21,8 +21,10 @@ import (
2121 "jfrog-credential-provider/internal/logger"
2222 "math/big"
2323 "os"
24+ "reflect"
2425 "slices"
2526 "strconv"
27+ "strings"
2628
2729 "gopkg.in/yaml.v3"
2830)
@@ -64,7 +66,10 @@ type Provider struct {
6466 DefaultCacheDuration string `json:"defaultCacheDuration" yaml:"defaultCacheDuration"`
6567 APIVersion string `json:"apiVersion" yaml:"apiVersion"`
6668 Env []EnvVar `json:"env,omitempty" yaml:"env,omitempty"`
69+ Args []string `json:"args,omitempty" yaml:"args,omitempty"`
6770 TokenAttributes * TokenAttributes `json:"tokenAttributes,omitempty" yaml:"tokenAttributes,omitempty"`
71+ // handling extra fields for the provider config
72+ ExtraFields map [string ]interface {} `json:"-" yaml:",inline"`
6873}
6974
7075type TokenAttributes struct {
@@ -86,6 +91,31 @@ type CredentialProviderConfig struct {
8691 Providers []Provider `json:"providers" yaml:"providers"`
8792}
8893
94+ func getStructFields (s interface {}) []string {
95+ fields := make ([]string , 0 )
96+ t := reflect .TypeOf (s )
97+
98+ if t .Kind () == reflect .Ptr {
99+ t = t .Elem ()
100+ }
101+
102+ for i := 0 ; i < t .NumField (); i ++ {
103+ field := t .Field (i )
104+ tag := field .Tag .Get ("json" )
105+ fieldName := strings .Split (tag , "," )[0 ]
106+ if fieldName == "-" {
107+ continue
108+ }
109+
110+ if fieldName == "" {
111+ fieldName = field .Name
112+ }
113+
114+ fields = append (fields , fieldName )
115+ }
116+ return fields
117+ }
118+
89119func (a AuthSection ) MarshalJSON () ([]byte , error ) {
90120 // Create a map to hold our custom JSON structure
91121 m := map [string ]interface {}{}
@@ -105,6 +135,51 @@ func (a *AuthSection) UnmarshalJSON(data []byte) error {
105135 return nil
106136}
107137
138+ func (p Provider ) MarshalJSON () ([]byte , error ) {
139+ type Alias Provider
140+
141+ standardBytes , err := json .Marshal ((* Alias )(& p ))
142+ if err != nil {
143+ return nil , err
144+ }
145+
146+ var finalMap map [string ]interface {}
147+ if err := json .Unmarshal (standardBytes , & finalMap ); err != nil {
148+ return nil , err
149+ }
150+ for key , value := range p .ExtraFields {
151+ finalMap [key ] = value
152+ }
153+
154+ return json .Marshal (finalMap )
155+ }
156+
157+ func (p * Provider ) UnmarshalJSON (data []byte ) error {
158+ type Alias Provider
159+ providerAliasMap := (* Alias )(p )
160+
161+ if err := json .Unmarshal (data , & providerAliasMap ); err != nil {
162+ return err
163+ }
164+
165+ // Unmarshal the raw JSON into a map to capture everything
166+ var allFields map [string ]interface {}
167+ if err := json .Unmarshal (data , & allFields ); err != nil {
168+ return err
169+ }
170+
171+ // Delete the known fields from the map to only keep the extra fields
172+ knownFields := getStructFields (p )
173+
174+ for _ , key := range knownFields {
175+ delete (allFields , key )
176+ }
177+
178+ // Assign the remaining fields to ExtraFields
179+ p .ExtraFields = allFields
180+ return nil
181+ }
182+
108183func GetEnvs (logs * logger.Logger , key , fallback string ) string {
109184 logs .Info ("Fetching environment variable:" + key )
110185 if value , ok := os .LookupEnv (key ); ok {
@@ -166,7 +241,6 @@ func ReadFile(filePath string, isYaml bool, v interface{}, cloudProvider string)
166241
167242func MergeFiles (file1 , file2 , outputFile string , isYaml , dryRun bool , logs * logger.Logger , cloudProvider string ) error {
168243 // Read and parse the first file
169-
170244 var config CredentialProviderConfig
171245
172246 // cloudProvider is being passed to be used by the validateJfrogProviderConfig function
0 commit comments