func (d *DBGenerator) setPasswordSecret(ctx context.Context) error {
	if d.Opts.Password == "" {
		return nil
	}
	d.Objs.HasPassword = true
	d.Objs.SuperuserPasswordSecret.TypeMeta.APIVersion = SecretAPIVersion
	d.Objs.SuperuserPasswordSecret.TypeMeta.Kind = SecretKindName
	d.Objs.SuperuserPasswordSecret.ObjectMeta.Name = fmt.Sprintf("%s-su-passwd", d.Opts.VdbName)
	d.Objs.Vdb.Spec.SuperuserPasswordSecret = d.Objs.SuperuserPasswordSecret.ObjectMeta.Name
	d.Objs.SuperuserPasswordSecret.Data = map[string][]byte{controllers.SuperuserPasswordKey: []byte(d.Opts.Password)}
	return nil
}
setPasswordSecret set the password secret fields
package vdbgen
import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"strings"
	_ "github.com/vertica/vertica-sql-go"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	vapi "github.com/vertica/vertica-kubernetes/api/v1beta1"
	"github.com/vertica/vertica-kubernetes/pkg/controllers"
	"github.com/vertica/vertica-kubernetes/pkg/paths"
)
type DBGenerator struct {
	Conn           *sql.DB
	Opts           *Options
	Objs           KObjs
	LicenseData    []byte
	DBCfg          map[string]string  
	CAFileData     []byte
	HadoopConfData map[string]string
}
type QueryType string
const (
	ShardCountKey      QueryType = "shardCount"
	DBCfgKey           QueryType = "dbCfg"
	StorageLocationKey QueryType = "storageLocation"
	SubclusterQueryKey QueryType = "subcluster"
	SecretAPIVersion = "v1"
	SecretKindName   = "Secret"
	ConfigAPIVersion = "v1"
	ConfigKindName   = "ConfigMap"
)
var Queries = map[QueryType]string{
	ShardCountKey:      "SELECT COUNT(*) FROM SHARDS WHERE SHARD_TYPE != 'Replica'",
	DBCfgKey:           "SHOW DATABASE DEFAULT ALL",
	StorageLocationKey: "SELECT NODE_NAME, LOCATION_PATH FROM STORAGE_LOCATIONS WHERE LOCATION_USAGE = ?",
	SubclusterQueryKey: "SELECT SUBCLUSTER_NAME, IS_PRIMARY FROM SUBCLUSTERS ORDER BY NODE_NAME",
}
func (d *DBGenerator) Create() (*KObjs, error) {
	ctx := context.Background()
	d.setParmsFromOptions()
	collectors := []func(ctx context.Context) error{
		d.readLicense,
		d.connect,
		d.setShardCount,
		d.setCommunalPath,
		d.fetchDatabaseConfig,
		d.setCommunalEndpointAWS,
		d.setCommunalEndpointGCloud,
		d.setCommunalEndpointAzure,
		d.setLocalPaths,
		d.setSubclusterDetail,
		d.setLicense,
		d.setPasswordSecret,
		d.readCAFile,
		d.setCAFile,
		d.readHadoopConfig,
		d.setHadoopConfig,
	}
	for _, collector := range collectors {
		if err := collector(ctx); err != nil {
			return nil, err
		}
	}
	return &d.Objs, nil
}
func (d *DBGenerator) connect(ctx context.Context) error {
	if d.Conn == nil {
		connStr := fmt.Sprintf("vertica://%s:%s@%s:%d/%s?tlsmode=%s",
			d.Opts.User, d.Opts.Password, d.Opts.Host, d.Opts.Port, d.Opts.DBName, d.Opts.TLSMode,
		)
		conn, err := sql.Open("vertica", connStr)
		if err != nil {
			return err
		}
		d.Conn = conn
	}
	return d.Conn.PingContext(ctx)
}
func (d *DBGenerator) setParmsFromOptions() {
	d.Objs.Vdb.TypeMeta.APIVersion = vapi.VerticaDBAPIVersion
	d.Objs.Vdb.TypeMeta.Kind = vapi.VerticaDBKind
	d.Objs.Vdb.Spec.InitPolicy = vapi.CommunalInitPolicyRevive
	d.Objs.Vdb.Spec.DBName = d.Opts.DBName
	d.Objs.Vdb.Spec.AutoRestartVertica = true
	d.Objs.Vdb.ObjectMeta.Name = d.Opts.VdbName
	d.Objs.Vdb.Spec.Local.RequestSize = resource.MustParse("100Mi")
	if d.Opts.IgnoreClusterLease {
		d.Objs.Vdb.Spec.IgnoreClusterLease = true
	}
	if d.Opts.Image != "" {
		d.Objs.Vdb.Spec.Image = d.Opts.Image
	}
	d.Objs.CredSecret.TypeMeta.APIVersion = SecretAPIVersion
	d.Objs.CredSecret.TypeMeta.Kind = SecretKindName
	d.Objs.CredSecret.ObjectMeta.Name = fmt.Sprintf("%s-credentials", d.Opts.VdbName)
	d.Objs.Vdb.Spec.Communal.CredentialSecret = d.Objs.CredSecret.ObjectMeta.Name
}
func (d *DBGenerator) setShardCount(ctx context.Context) error {
	q := Queries[ShardCountKey]
	rows, err := d.Conn.QueryContext(ctx, q)
	if err != nil {
		return fmt.Errorf("failed running '%s': %w", q, err)
	}
	defer rows.Close()
	if rows.Err() != nil {
		return fmt.Errorf("failed running '%s': %w", q, rows.Err())
	}
	if !rows.Next() {
		return errors.New("did find any rows in SHARDS")
	}
	if err := rows.Scan(&d.Objs.Vdb.Spec.ShardCount); err != nil {
		return fmt.Errorf("failed running '%s': %w", q, err)
	}
	return nil
}
func (d *DBGenerator) fetchDatabaseConfig(ctx context.Context) error {
	q := Queries[DBCfgKey]
	rows, err := d.Conn.QueryContext(ctx, q)
	if err != nil {
		return fmt.Errorf("failed running '%s': %w", q, err)
	}
	defer rows.Close()
	d.DBCfg = map[string]string{}
	for rows.Next() {
		if rows.Err() != nil {
			return fmt.Errorf("failed running '%s': %w", q, rows.Err())
		}
		var key string
		var value string
		if err := rows.Scan(&key, &value); err != nil {
			return fmt.Errorf("failed running '%s': %w", q, err)
		}
		d.DBCfg[key] = value
	}
	return nil
}
func (d *DBGenerator) setCommunalEndpointAWS(ctx context.Context) error {
	if !d.Objs.Vdb.IsS3() {
		return nil
	}
	const HTTPSKey = "AWSEnableHttps"
	const EndpointKey = "AWSEndpoint"
	const AWSAuth = "AWSAuth"
	const RegionKey = "AWSRegion"
	return d.setCommunalEndpointGeneric(HTTPSKey, EndpointKey, AWSAuth, RegionKey)
}
func (d *DBGenerator) setCommunalEndpointGCloud(ctx context.Context) error {
	if !d.Objs.Vdb.IsGCloud() {
		return nil
	}
	const HTTPSKey = "GCSEnableHttps"
	const EndpointKey = "GCSEndpoint"
	const AWSAuth = "GCSAuth"
	const RegionKey = "GCSRegion"
	return d.setCommunalEndpointGeneric(HTTPSKey, EndpointKey, AWSAuth, RegionKey)
}
func (d *DBGenerator) setCommunalEndpointAzure(ctx context.Context) error {
	if !d.Objs.Vdb.IsAzure() {
		return nil
	}
	const AzureCredentialKey = "AzureStorageCredentials"
	const AzureConfigKey = "AzureStorageEndpointConfig"
	credsStr, ok := d.DBCfg[AzureCredentialKey]
	if !ok {
		return nil
	}
	cred, ok, err := d.extractAzureCredential(credsStr)
	if !ok || err != nil {
		return err
	}
	blobEndpoint := cred.BlobEndpoint
	epCfg := controllers.AzureEndpointConfig{}
	configStr, ok := d.DBCfg[AzureConfigKey]
	if ok {
		epCfg, ok, err = d.extractAzureEndpointConfig(configStr)
		if err != nil {
			return err
		}
		if ok && epCfg.Protocol != "" {
			blobEndpoint = fmt.Sprintf("%s://%s", epCfg.Protocol, cred.BlobEndpoint)
		}
	}
	d.Objs.CredSecret.Data = map[string][]byte{}
	if cred.AccountKey != "" {
		d.Objs.CredSecret.Data[controllers.AzureAccountKey] = []byte(cred.AccountKey)
	}
	if cred.AccountName != "" {
		d.Objs.CredSecret.Data[controllers.AzureAccountName] = []byte(cred.AccountName)
	}
	if cred.BlobEndpoint != "" {
		d.Objs.CredSecret.Data[controllers.AzureBlobEndpoint] = []byte(blobEndpoint)
	}
	if cred.SharedAccessSignature != "" {
		d.Objs.CredSecret.Data[controllers.AzureSharedAccessSignature] = []byte(cred.SharedAccessSignature)
	}
	return nil
}
func (d *DBGenerator) setCommunalEndpointGeneric(httpsKey, endpointKey, authKey, regionKey string) error {
	var protocol, endpoint string
	var auth []string
	value, ok := d.DBCfg[httpsKey]
	if !ok {
		return nil
	}
	if value == "0" {
		protocol = "http"
	} else {
		protocol = "https"
	}
	value, ok = d.DBCfg[endpointKey]
	if !ok {
		return fmt.Errorf("missing '%s' in query '%s'", endpointKey, Queries[DBCfgKey])
	}
	endpoint = value
	value, ok = d.DBCfg[authKey]
	if !ok {
		return fmt.Errorf("missing '%s' in query '%s'", authKey, Queries[DBCfgKey])
	}
	authRE := regexp.MustCompile(`:`)
	const NumAuthComponents = 2
	auth = authRE.Split(value, NumAuthComponents)
	value, ok = d.DBCfg[regionKey]
	if ok {
		d.Objs.Vdb.Spec.Communal.Region = value
	}
	d.Objs.Vdb.Spec.Communal.Endpoint = fmt.Sprintf("%s://%s", protocol, endpoint)
	d.Objs.CredSecret.Data = map[string][]byte{
		controllers.CommunalAccessKeyName: []byte(auth[0]),
		controllers.CommunalSecretKeyName: []byte(auth[1]),
	}
	return nil
}
func (d *DBGenerator) setLocalPaths(ctx context.Context) error {
	dataPath, err := d.queryLocalPath(ctx, "DATA,TEMP")
	if err != nil {
		return err
	}
	d.Objs.Vdb.Spec.Local.DataPath = dataPath
	depotPath, err := d.queryLocalPath(ctx, "DEPOT")
	if err != nil {
		return err
	}
	d.Objs.Vdb.Spec.Local.DepotPath = depotPath
	return nil
}
func (d *DBGenerator) setCommunalPath(ctx context.Context) error {
	var communalPath string
	extractPath := func(nodeName, nodePath sql.NullString) error {
		if !nodePath.Valid {
			return errors.New("node path is NULL")
		}
		communalPath = nodePath.String
		return nil
	}
	if err := d.queryPathForUsage(ctx, "DATA", extractPath); err != nil {
		return err
	}
	d.Objs.Vdb.Spec.Communal.Path = communalPath
	return nil
}
func (d *DBGenerator) queryPathForUsage(ctx context.Context, usage string,
	extractFunc func(nodeName, nodePath sql.NullString) error) error {
	q := Queries[StorageLocationKey]
	rows, err := d.Conn.QueryContext(ctx, q, usage)
	if err != nil {
		return err
	}
	defer rows.Close()
	for rows.Next() {
		if rows.Err() != nil {
			return fmt.Errorf("failed running '%s': %w", q, rows.Err())
		}
		var nodeName sql.NullString
		var nodePath sql.NullString
		if err := rows.Scan(&nodeName, &nodePath); err != nil {
			return fmt.Errorf("failed running '%s': %w", q, err)
		}
		if err := extractFunc(nodeName, nodePath); err != nil {
			return err
		}
	}
	return nil
}
func (d *DBGenerator) queryLocalPath(ctx context.Context, usage string) (string, error) {
	var commonPrefix string
	extractCommonPrefix := func(nodeName, nodePath sql.NullString) error {
		curCommonPrefix := path.Dir(path.Dir(nodePath.String))
		if len(commonPrefix) > 0 && commonPrefix != curCommonPrefix {
			return fmt.Errorf(
				"location path for usage '%s' must be the same across all nodes -- path '%s' does not share the common prefix from other nodes '%s'",
				usage, nodePath.String, commonPrefix)
		}
		commonPrefix = curCommonPrefix
		return nil
	}
	if err := d.queryPathForUsage(ctx, usage, extractCommonPrefix); err != nil {
		return "", err
	}
	if commonPrefix == "" {
		return "", fmt.Errorf("failed to find any location path for usage '%s'", usage)
	}
	return commonPrefix, nil
}
func (d *DBGenerator) setSubclusterDetail(ctx context.Context) error {
	q := Queries[SubclusterQueryKey]
	rows, err := d.Conn.QueryContext(ctx, q)
	if err != nil {
		return fmt.Errorf("failed running '%s': %w", q, err)
	}
	defer rows.Close()
	subclusterInxMap := map[string]int{}
	for rows.Next() {
		if rows.Err() != nil {
			return fmt.Errorf("failed running '%s': %w", q, rows.Err())
		}
		var name string
		var isPrimary bool
		if err := rows.Scan(&name, &isPrimary); err != nil {
			return fmt.Errorf("failed running '%s': %w", q, err)
		}
		if !vapi.IsValidSubclusterName(name) {
			return fmt.Errorf("subcluster names are included in the name of statefulsets, but the name "+
				"'%s' cannot be used as it will violate Kubernetes naming.  Please rename the subcluster and "+
				"retry this command again", name)
		}
		inx, ok := subclusterInxMap[name]
		if !ok {
			inx = len(d.Objs.Vdb.Spec.Subclusters)
			d.Objs.Vdb.Spec.Subclusters = append(d.Objs.Vdb.Spec.Subclusters,
				vapi.Subcluster{Name: name, Size: 0, IsPrimary: isPrimary})
			subclusterInxMap[name] = inx
		}
		d.Objs.Vdb.Spec.Subclusters[inx].Size++
		revSz := len(d.Objs.Vdb.Spec.ReviveOrder)
		if revSz == 0 || d.Objs.Vdb.Spec.ReviveOrder[revSz-1].SubclusterIndex != inx {
			d.Objs.Vdb.Spec.ReviveOrder = append(d.Objs.Vdb.Spec.ReviveOrder, vapi.SubclusterPodCount{SubclusterIndex: inx, PodCount: 1})
		} else {
			d.Objs.Vdb.Spec.ReviveOrder[revSz-1].PodCount++
		}
	}
	if len(subclusterInxMap) == 0 {
		return errors.New("not subclusters found")
	}
	return nil
}
func (d *DBGenerator) setLicense(ctx context.Context) error {
	if len(d.LicenseData) == 0 {
		return nil
	}
	d.Objs.HasLicense = true
	d.Objs.LicenseSecret.TypeMeta.APIVersion = SecretAPIVersion
	d.Objs.LicenseSecret.TypeMeta.Kind = SecretKindName
	d.Objs.LicenseSecret.ObjectMeta.Name = fmt.Sprintf("%s-license", d.Opts.VdbName)
	d.Objs.Vdb.Spec.LicenseSecret = d.Objs.LicenseSecret.ObjectMeta.Name
	d.Objs.LicenseSecret.Data = map[string][]byte{"license.dat": d.LicenseData}
	return nil
}
func (d *DBGenerator) readLicense(ctx context.Context) error {
	if d.Opts.LicenseFile == "" {
		return nil
	}
	var err error
	d.LicenseData, err = ioutil.ReadFile(d.Opts.LicenseFile)
	if err != nil {
		return err
	}
	return nil
}