Skip to content

Commit 98ef719

Browse files
committed
feat(cli): stores import csv add support for store Password to be a PAM provider.
fix(cli): `stores import csv` properly handles "ServerUsername" and "ServerPassword" properties. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com>
1 parent a75ab62 commit 98ef719

1 file changed

Lines changed: 70 additions & 26 deletions

File tree

cmd/storesBulkOperations.go

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,18 @@ func formatProperties(json *gabs.Container, reqPropertiesForStoreType []string)
7272
log.Debug().Str("name", name).Msg("Property is nil")
7373
continue
7474
}
75-
if intValue, isInt := prop.Data().(int); isInt {
75+
switch prop.Data().(type) {
76+
case int:
7677
log.Debug().Str("name", name).Msg("Property is an int")
77-
asStr := strconv.Itoa(intValue)
78+
asStr := strconv.Itoa(prop.Data().(int))
7879
// Use gabs' Set method to update the property value
7980
json.Set(asStr, "Properties", name)
81+
case map[string]interface{}:
82+
if name == "ServerUsername" || name == "ServerPassword" {
83+
reformatted := reformatPamSecretForPost(prop.Data().(map[string]interface{}))
84+
json.Set(reformatted["value"], "Properties", name)
85+
break
86+
}
8087
}
8188
}
8289
return json
@@ -259,11 +266,19 @@ If you do not wish to include credentials in your CSV file they can be provided
259266
exists := false
260267
for _, headerField := range headerRow {
261268
log.Debug().Msgf("Checking for required field %s in header '%s'", reqField, headerField)
262-
if strings.EqualFold(headerField, "Properties."+reqField) {
269+
if strings.EqualFold(headerField, "Properties."+reqField) || strings.HasPrefix(
270+
headerField, "Properties."+reqField,
271+
) {
272+
log.Debug().Msgf("Found required field %s in header '%s'", reqField, headerField)
273+
exists = true
274+
continue
275+
}
276+
if strings.EqualFold(reqField, "Password") && strings.Contains(headerField, "Password.") {
263277
log.Debug().Msgf("Found required field %s in header '%s'", reqField, headerField)
264278
exists = true
265279
continue
266280
}
281+
267282
}
268283
if !exists {
269284
log.Debug().Msgf("Missing required field '%s'", reqField)
@@ -332,6 +347,9 @@ If you do not wish to include credentials in your CSV file they can be provided
332347
}
333348

334349
storeId := reqJson.S("Id").String()
350+
if storeId == "{}" {
351+
storeId = ""
352+
}
335353
if storeId != "" && allowUpdates {
336354
log.Debug().Str("storeId", storeId).Msgf("Store Id present in row, will attempt update operation")
337355
}
@@ -340,6 +358,8 @@ If you do not wish to include credentials in your CSV file they can be provided
340358
// parse properties
341359
props := unmarshalPropertiesString(reqJson.S("Properties").String())
342360

361+
//props = formatStoreProperties(props)
362+
343363
//check if ServerUsername is present in the properties
344364
_, uOk := props["ServerUsername"]
345365
if !uOk && serverUsername != "" {
@@ -351,17 +371,32 @@ If you do not wish to include credentials in your CSV file they can be provided
351371
props["ServerPassword"] = serverPassword
352372
}
353373

354-
rowStorePassword := reqJson.S("Password").String()
355374
reqJson.Delete("Properties") // todo: why is this deleting the properties from the request json?
356-
var passwdParams *api.StorePasswordConfig
357-
if rowStorePassword != "" {
358-
reqJson.Delete("Password")
359-
passwdParams = &api.StorePasswordConfig{
360-
Value: &rowStorePassword,
375+
376+
rowStorePassword := reqJson.S("Password").Data()
377+
passwdParams := api.UpdateStorePasswordConfig{
378+
SecretValue: nil,
379+
}
380+
switch rowStorePassword.(type) {
381+
case string:
382+
if rowStorePassword != "" {
383+
reqJson.Delete("Password")
384+
passwdValue := rowStorePassword.(string)
385+
passwdParams.SecretValue = &passwdValue
361386
}
362-
} else {
363-
passwdParams = &api.StorePasswordConfig{
364-
Value: &storePassword,
387+
case map[string]interface{}:
388+
// try to convert it to api.UpdateStorePasswordConfig
389+
rowPasswordMap := rowStorePassword.(map[string]interface{})
390+
if providerId, ok := rowPasswordMap["ProviderId"].(int); ok {
391+
passwdParams.Provider = providerId
392+
}
393+
if params, ok := rowPasswordMap["Parameters"].(map[string]interface{}); ok {
394+
for k, v := range params {
395+
if passwdParams.Parameters == nil {
396+
passwdParams.Parameters = make(map[string]string)
397+
}
398+
passwdParams.Parameters[k] = fmt.Sprintf("%v", v)
399+
}
365400
}
366401
}
367402

@@ -378,7 +413,11 @@ If you do not wish to include credentials in your CSV file they can be provided
378413
return conversionError
379414
}
380415

381-
updateReqParameters.Password = passwdParams
416+
updateReqParameters.Password = &api.UpdateStorePasswordConfig{
417+
Provider: passwdParams.Provider,
418+
Parameters: nil,
419+
SecretValue: passwdParams.SecretValue,
420+
}
382421
updateReqParameters.Properties = props
383422
log.Info().Msgf("Calling Command to update store from row '%d'", idx)
384423
res, err := kfClient.UpdateStore(&updateReqParameters)
@@ -405,20 +444,26 @@ If you do not wish to include credentials in your CSV file they can be provided
405444
"Unable to convert the json into the request parameters object. %s",
406445
conversionError.Error(),
407446
)
408-
return conversionError
409447
}
410448

411-
createStoreReqParameters.Password = passwdParams
449+
createStoreReqParameters.Password = &passwdParams
450+
451+
//if storePassword == "" {
452+
// storePassword = "meow123!" // default password if none provided
453+
//}
454+
//createStoreReqParameters.Password = &api.UpdateStorePasswordConfig{
455+
// SecretValue: &storePassword,
456+
//}
412457
createStoreReqParameters.Properties = props
413458
//log.Debug().Msgf("Request parameters: %v", createStoreReqParameters)
414459

415460
log.Info().Msgf("Calling Command to create store from row '%d'", idx)
416-
res, err := kfClient.CreateStore(&createStoreReqParameters)
461+
res, cErr := kfClient.CreateStore(&createStoreReqParameters)
417462

418-
if err != nil {
419-
log.Error().Err(err).Msgf("Error creating store from row '%d'", idx)
420-
resultsMap = append(resultsMap, []string{err.Error()})
421-
inputMap[idx-1]["Errors"] = err.Error()
463+
if cErr != nil {
464+
log.Error().Err(cErr).Msgf("Error creating store from row '%d'", idx)
465+
resultsMap = append(resultsMap, []string{cErr.Error()})
466+
inputMap[idx-1]["Errors"] = cErr.Error()
422467
inputMap[idx-1]["Id"] = "error"
423468
errorCount++
424469
} else {
@@ -488,11 +533,6 @@ Store type IDs can be found by running the "store-types" command.`,
488533
storeTypeID, _ := cmd.Flags().GetInt("store-type-id")
489534
outpath, _ := cmd.Flags().GetString("outpath")
490535

491-
//inputErr := storeTypeIdentifierFlagCheck(cmd)
492-
//if inputErr != nil {
493-
// return inputErr
494-
//}
495-
496536
// expEnabled checks
497537
isExperimental := false
498538
debugErr := warnExperimentalFeature(expEnabled, isExperimental)
@@ -571,7 +611,6 @@ Store type IDs can be found by running the "store-types" command.`,
571611
sTypeShortName = storeTypeName
572612
}
573613

574-
// write csv file header row
575614
var filePath string
576615
if outpath != "" {
577616
filePath = outpath
@@ -1052,10 +1091,15 @@ func getRequiredProperties(id interface{}, kfClient api.Client) (int64, []string
10521091
reqProps := make([]string, 0)
10531092
for _, prop := range properties {
10541093
if prop.S("Required").Data() == true {
1094+
log.Debug().Str("property", prop.S("Name").Data().(string)).
1095+
Msg("Is required")
10551096
name := prop.S("Name")
10561097
reqProps = append(reqProps, name.Data().(string))
10571098
}
10581099
}
1100+
//if storeType.PasswordOptions.StoreRequired {
1101+
// reqProps = append(reqProps, "Password")
1102+
//}
10591103
intId, _ := jsonParsedObj.S("StoreType").Data().(json.Number).Int64()
10601104

10611105
return intId, reqProps, nil

0 commit comments

Comments
 (0)