112 lines
2.6 KiB
Go
112 lines
2.6 KiB
Go
|
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||
|
//
|
||
|
// Helper methods for OCI GOSDK Samples
|
||
|
//
|
||
|
|
||
|
package helpers
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"math/rand"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// LogIfError is equivalent to Println() followed by a call to os.Exit(1) if error is not nil
|
||
|
func LogIfError(err error) {
|
||
|
if err != nil {
|
||
|
log.Fatalln(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// RetryUntilTrueOrError retries a function until the predicate is true or it reaches a timeout.
|
||
|
// The operation is retried at the give frequency
|
||
|
func RetryUntilTrueOrError(operation func() (interface{}, error), predicate func(interface{}) (bool, error), frequency, timeout <-chan time.Time) error {
|
||
|
for {
|
||
|
select {
|
||
|
case <-timeout:
|
||
|
return fmt.Errorf("timeout reached")
|
||
|
case <-frequency:
|
||
|
result, err := operation()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
isTrue, err := predicate(result)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if isTrue {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// FindLifecycleFieldValue finds lifecycle value inside the struct based on reflection
|
||
|
func FindLifecycleFieldValue(request interface{}) (string, error) {
|
||
|
val := reflect.ValueOf(request)
|
||
|
if val.Kind() == reflect.Ptr {
|
||
|
if val.IsNil() {
|
||
|
return "", fmt.Errorf("can not unmarshal to response a pointer to nil structure")
|
||
|
}
|
||
|
val = val.Elem()
|
||
|
}
|
||
|
|
||
|
var err error
|
||
|
typ := val.Type()
|
||
|
for i := 0; i < typ.NumField(); i++ {
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
sf := typ.Field(i)
|
||
|
|
||
|
//unexported
|
||
|
if sf.PkgPath != "" {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
sv := val.Field(i)
|
||
|
|
||
|
if sv.Kind() == reflect.Struct {
|
||
|
lif, err := FindLifecycleFieldValue(sv.Interface())
|
||
|
if err == nil {
|
||
|
return lif, nil
|
||
|
}
|
||
|
}
|
||
|
if !strings.Contains(strings.ToLower(sf.Name), "lifecyclestate") {
|
||
|
continue
|
||
|
}
|
||
|
return sv.String(), nil
|
||
|
}
|
||
|
return "", fmt.Errorf("request does not have a lifecycle field")
|
||
|
}
|
||
|
|
||
|
// CheckLifecycleState returns a function that checks for that a struct has the given lifecycle
|
||
|
func CheckLifecycleState(lifecycleState string) func(interface{}) (bool, error) {
|
||
|
return func(request interface{}) (bool, error) {
|
||
|
fieldLifecycle, err := FindLifecycleFieldValue(request)
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
isEqual := fieldLifecycle == lifecycleState
|
||
|
log.Printf("Current lifecycle state is: %s, waiting for it becomes to: %s", fieldLifecycle, lifecycleState)
|
||
|
return isEqual, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// GetRandomString returns a random string with length equals to n
|
||
|
func GetRandomString(n int) string {
|
||
|
letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||
|
|
||
|
b := make([]rune, n)
|
||
|
for i := range b {
|
||
|
b[i] = letters[rand.Intn(len(letters))]
|
||
|
}
|
||
|
return string(b)
|
||
|
}
|