func contains(key string, keys []string) bool {
	for _, k := range keys {
		if k == key {
			return true
		}
	}
	return false
}
contains checks if a given key is in a slice of keys.
package vault
import (
	b64 "encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"path"
	"strconv"
	"strings"
	"time"
	"github.com/hashicorp/vault/api"
)
type RequestToken func(*Client) error
type Client struct {
	client *api.Client
	tokenLeaseDuration int
	tokenRenewalInterval float64
	tokenRenewalRetryInterval float64
	tokenMaxTTL int
	requestToken RequestToken
	rootVaultNamespace string
	failedRenewTokenAttempts int
}
func (c *Client) RenewToken() {
	started := time.Now()
	for {
		if c.rootVaultNamespace != "" {
			c.client.SetNamespace(c.rootVaultNamespace)
		}
		elapsed := time.Now().Sub(started).Seconds()
		if c.tokenMaxTTL > 0 && elapsed >= float64(c.tokenMaxTTL) && c.requestToken != nil {
			log.Info("Request new Vault token")
			err := c.requestToken(c)
			if err != nil {
				log.Error(err, "Could not request a new token")
				c.failedRenewTokenAttempts = c.failedRenewTokenAttempts + 1
				time.Sleep(time.Duration(c.tokenRenewalRetryInterval) * time.Second)
			} else {
				c.failedRenewTokenAttempts = 0
				started = time.Now()
				time.Sleep(time.Duration(c.tokenRenewalInterval) * time.Second)
			}
			continue
		}
		log.Info("Renew Vault token")
		_, err := c.client.Auth().Token().RenewSelf(c.tokenLeaseDuration)
		if err != nil {
			log.Error(err, "Could not renew token")
			c.failedRenewTokenAttempts = c.failedRenewTokenAttempts + 1
			time.Sleep(time.Duration(c.tokenRenewalRetryInterval) * time.Second)
		} else {
			c.failedRenewTokenAttempts = 0
			time.Sleep(time.Duration(c.tokenRenewalInterval) * time.Second)
		}
	}
}
func (c *Client) GetHealth(threshold int) error {
	if c.failedRenewTokenAttempts >= threshold {
		return fmt.Errorf("Renew Vault token failed %d times", c.failedRenewTokenAttempts)
	}
	return nil
}
func (c *Client) GetSecret(secretEngine string, path string, keys []string, version int, isBinary bool, vaultNamespace string) (map[string][]byte, error) {
	log.Info(fmt.Sprintf("Read secret %s", path))
	if c.rootVaultNamespace != "" {
		log.WithValues("rootVaultNamespace", c.rootVaultNamespace, "vaultNamespace", vaultNamespace).Info(fmt.Sprintf("Use Vault Namespace to read secret %s", path))
		if vaultNamespace != "" {
			c.client.SetNamespace(c.rootVaultNamespace + "/" + vaultNamespace)
		} else {
			c.client.SetNamespace(c.rootVaultNamespace)
		}
	} else if c.rootVaultNamespace == "" && vaultNamespace != "" {
		return nil, fmt.Errorf("vaultNamespace field can not be used, because the VAULT_NAMESPACE environment variable is not set")
	}
	mountPath, v2, err := c.isKVv2(path)
	if err != nil {
		return nil, err
	}
	reqData := make(map[string][]string)
	if v2 {
		path = c.addPrefixToVKVPath(path, mountPath, "data")
		if version > 0 {
			reqData["version"] = []string{strconv.Itoa(version)}
		}
	}
	secret, err := c.client.Logical().ReadWithData(path, reqData)
	if err != nil {
		return nil, err
	}
	if secret == nil {
		return nil, fmt.Errorf("secret is nil")
	}
	secretData := secret.Data
	if v2 {
		var ok bool
		secretData, ok = secret.Data["data"].(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("could not parse secret")
		}
	}
	data := make(map[string][]byte)
	for key, value := range secretData {
		if value == nil {
			continue
		}
		if len(keys) == 0 || contains(key, keys) {
			switch value.(type) {
			case map[string]interface{}:
				jsonString, err := json.Marshal(value)
				if err != nil {
					return nil, err
				}
				data[key] = []byte(jsonString)
			case string:
				if isBinary {
					data[key], err = b64.StdEncoding.DecodeString(value.(string))
					if err != nil {
						return nil, err
					}
				} else {
					data[key] = []byte(value.(string))
				}
			case json.Number:
				data[key] = []byte(value.(json.Number))
			case bool:
				data[key] = []byte(fmt.Sprintf("%t", value.(bool)))
			default:
				return nil, fmt.Errorf("could not parse secret value")
			}
		}
	}
	if len(data) == 0 {
		return nil, fmt.Errorf("invalid secret data")
	}
	return data, nil
}