func Postgresql(mode string, port string, clusterType string) (string, error) {
	var info PostgresqlParameters
	info.PG_PORT = port
	info.CLUSTER_TYPE = clusterType

	var path string
	switch mode {
	case "standalone", "master", "standby":
		path = util.GetBase() + "/conf/" + mode + "/postgresql.conf.template"
	default:
		return "", errors.New("invalid mode in processPostgresql of " + mode)
	}

	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	tmpl, err := template.New("postgresql").Parse(string(contents))
	if err != nil {
		return "", err
	}
	buff := bytes.NewBufferString("")
	err = tmpl.Execute(buff, info)

	return buff.String(), nil
}
func KubeNodeService(info KubeServiceParams) ([]byte, error) {

	var path string
	path = util.GetBase() + "/conf/" + "service-template.json"

	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	tmpl, err := template.New("kube").Parse(string(contents))
	if err != nil {
		return nil, err
	}
	buff := bytes.NewBufferString("")
	err = tmpl.Execute(buff, info)

	return buff.Bytes(), nil
}
//
// Poolconf generates a pgpool.conf file from a template and
// values passed in
//
func Poolconf(poolnames []string) (string, error) {

	var poolParams PGPoolParameters
	poolParams.HOST_LIST = poolnames
	var path = util.GetBase() + "/conf/" + "pgpool/pgpool.conf.template"

	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	tmpl, err := template.New("pgpoolconf").Parse(string(contents))
	if err != nil {
		return "", err
	}
	buff := bytes.NewBufferString("")

	err = tmpl.Execute(buff, poolParams)
	logit.Info.Println("Poolconf:" + buff.String())

	return buff.String(), nil
}
//
// Poolpasswd right now this is simple, just read the template and spit it back
// out, no substitutions are done right now, they will be in the future no doubt
//
func Poolpasswd() (string, error) {

	var info RecoveryParameters

	var path = util.GetBase() + "/conf/" + "pgpool/pool_passwd.template"

	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	tmpl, err := template.New("pgpoolpasswd").Parse(string(contents))
	if err != nil {
		return "", err
	}
	buff := bytes.NewBufferString("")

	err = tmpl.Execute(buff, info)
	logit.Info.Println("Poolpasswd:" + buff.String())

	return buff.String(), nil
}
func Recovery(masterhost string, port string, masteruser string) (string, error) {
	var info RecoveryParameters
	info.PG_PORT = port
	info.USER = masteruser
	info.PG_HOST_IP = masterhost

	var path string
	path = util.GetBase() + "/conf/" + "standby/recovery.conf.template"

	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	tmpl, err := template.New("recovery").Parse(string(contents))
	if err != nil {
		return "", err
	}
	buff := bytes.NewBufferString("")
	err = tmpl.Execute(buff, info)

	return buff.String(), nil
}
func Hba(dbConn *sql.DB, mode string, hostname string, port string, clusterid string, domainname string, cars []Rule) (string, error) {

	var hbaInfo HBAParameters

	hbaInfo.PG_HOST_IP = hostname + "." + domainname
	hbaInfo.BACKUP_HOST = hostname + "-backup." + domainname
	hbaInfo.MONITOR_HOST = "cpm-mon." + domainname
	hbaInfo.ADMIN_HOST = "cpm-admin." + domainname
	hbaInfo.RULES_LIST = cars

	servers, err := admindb.GetAllServers(dbConn)
	if err != nil {
		logit.Error.Println("Hba:" + err.Error())
		return "", err
	}

	i := 0
	var allservers = ""
	var allbridges = ""
	for i = range servers {
		logit.Info.Println("Hba:" + servers[i].IPAddress)
		if allservers == "" {
			allservers = servers[i].IPAddress
			allbridges = servers[i].DockerBridgeIP
		} else {
			allservers = allservers + ":" + servers[i].IPAddress
			allbridges = allbridges + ":" + servers[i].DockerBridgeIP
		}
	}
	logit.Info.Println("Hba:processing serverlist=" + allservers)
	hbaInfo.SERVER_IP_LIST = strings.Split(allservers, ":")
	hbaInfo.BRIDGE_IP_LIST = strings.Split(allbridges, ":")

	var path string
	switch mode {
	case "unassigned":
		path = util.GetBase() + "/conf/standalone/pg_hba.conf.template"
	case "standalone", "master", "standby":
		path = util.GetBase() + "/conf/" + mode + "/pg_hba.conf.template"
	default:
		return "", errors.New("invalid mode in processHba of " + mode)
	}

	if mode == "standby" || mode == "master" {
		_, pgpoolNode, standbyList, err := getMasterValues(dbConn, clusterid, domainname)
		if err != nil {
			return "", err
		}

		hbaInfo.PGPOOL_HOST = pgpoolNode.Name + "." + domainname
		hbaInfo.STANDBY_LIST = standbyList
	}

	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}

	tmpl, err := template.New("hba").Parse(string(contents))
	if err != nil {
		return "", err
	}
	buff := bytes.NewBufferString("")

	logInfo(hbaInfo)

	err = tmpl.Execute(buff, hbaInfo)
	logit.Info.Println("Hba:" + buff.String())

	return buff.String(), nil
}
func configureCluster(dbConn *sql.DB, cluster admindb.Cluster, autocluster bool) error {
	logit.Info.Println("configureCluster:GetCluster")

	//get master node for this cluster
	master, err := admindb.GetContainerMaster(dbConn, cluster.ID)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:GetContainerMaster")

	//configure master postgresql.conf file
	var data string
	if cluster.ClusterType == "synchronous" {
		data, err = template.Postgresql("master", pgport.Value, "*")
	} else {
		data, err = template.Postgresql("master", pgport.Value, "")
	}
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:master postgresql.conf generated")

	//write master postgresql.conf file remotely
	_, err = cpmcontainerapi.RemoteWritefileClient("/pgdata/postgresql.conf", data, master.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:master postgresql.conf copied to remote")

	//get domain name
	var domainname admindb.Setting
	domainname, err = admindb.GetSetting(dbConn, "DOMAIN-NAME")
	if err != nil {
		logit.Error.Println("configureCluster: DOMAIN-NAME err " + err.Error())
		return err
	}

	//configure master pg_hba.conf file
	rules := make([]template.Rule, 0)
	data, err = template.Hba(dbConn, "master", master.Name, pgport.Value, cluster.ID, domainname.Value, rules)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:master pg_hba.conf generated")

	//write master pg_hba.conf file remotely
	_, err = cpmcontainerapi.RemoteWritefileClient("/pgdata/pg_hba.conf", data, master.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:master pg_hba.conf copied remotely")

	//restart postgres after the config file changes
	var stopResp cpmcontainerapi.StopPGResponse
	stopResp, err = cpmcontainerapi.StopPGClient(master.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	logit.Info.Println("configureCluster: master stoppg output was" + stopResp.Output)

	var startResp cpmcontainerapi.StartPGResponse
	startResp, err = cpmcontainerapi.StartPGClient(master.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	logit.Info.Println("configureCluster:master startpg output was" + startResp.Output)

	//sleep loop until the master's PG can respond
	var found = false
	var currentStatus string
	var masterhost = master.Name
	for i := 0; i < 20; i++ {
		currentStatus, err = GetPGStatus2(dbConn, master.Name, masterhost)
		if currentStatus == "RUNNING" {
			logit.Info.Println("master is running...continuing")
			found = true
			break
		} else {
			logit.Info.Println("sleeping 1 sec waiting on master..")
			time.Sleep(1000 * time.Millisecond)
		}
	}
	if !found {
		logit.Info.Println("configureCluster: timed out waiting on master pg to start")
		return errors.New("timeout waiting for master pg to respond")
	}

	standbynodes, err2 := admindb.GetAllStandbyContainers(dbConn, cluster.ID)
	if err2 != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	//configure all standby nodes
	var stopPGResp cpmcontainerapi.StopPGResponse
	i := 0
	for i = range standbynodes {
		if standbynodes[i].Role == STANDBY {

			//stop standby
			if !autocluster {
				stopPGResp, err = cpmcontainerapi.StopPGClient(standbynodes[i].Name)
				if err != nil {
					logit.Error.Println("configureCluster:" + err.Error())
					return err
				}
				logit.Info.Println("configureCluster:stop output was" + stopPGResp.Output)
			}

			//create base backup from master
			var backupresp cpmcontainerapi.BasebackupResponse
			backupresp, err = cpmcontainerapi.BasebackupClient(masterhost+"."+domainname.Value, standbynodes[i].Name)
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}
			logit.Info.Println("configureCluster:basebackup output was" + backupresp.Output)

			data, err = template.Recovery(masterhost, pgport.Value, "postgres")
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}
			logit.Info.Println("configureCluster:standby recovery.conf generated")

			//write standby recovery.conf file remotely
			_, err = cpmcontainerapi.RemoteWritefileClient("/pgdata/recovery.conf", data, standbynodes[i].Name)
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}
			logit.Info.Println("configureCluster:standby recovery.conf copied remotely")

			data, err = template.Postgresql(STANDBY, pgport.Value, "")
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}

			//write standby postgresql.conf file remotely
			_, err = cpmcontainerapi.RemoteWritefileClient("/pgdata/postgresql.conf", data, standbynodes[i].Name)
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}
			logit.Info.Println("configureCluster:standby postgresql.conf copied remotely")

			//configure standby pg_hba.conf file
			data, err = template.Hba(dbConn, STANDBY, standbynodes[i].Name, pgport.Value, cluster.ID, domainname.Value, rules)
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}

			logit.Info.Println("configureCluster:standby pg_hba.conf generated")

			//write standby pg_hba.conf file remotely
			_, err = cpmcontainerapi.RemoteWritefileClient("/pgdata/pg_hba.conf", data, standbynodes[i].Name)
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}
			logit.Info.Println("configureCluster:standby pg_hba.conf copied remotely")

			//start standby

			var stResp cpmcontainerapi.StartPGOnStandbyResponse
			stResp, err = cpmcontainerapi.StartPGOnStandbyClient(standbynodes[i].Name)
			if err != nil {
				logit.Error.Println("configureCluster:" + err.Error())
				return err
			}
			logit.Info.Println("configureCluster:standby startpg output was" + stResp.Output)
		}
		i++
	}

	logit.Info.Println("configureCluster: sleeping 5 seconds before configuring pgpool...")
	time.Sleep(5000 * time.Millisecond)

	pgpoolNode, err4 := admindb.GetContainerPgpool(dbConn, cluster.ID)
	logit.Info.Println("configureCluster: lookup pgpool node")
	if err4 != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	logit.Info.Println("configureCluster:" + pgpoolNode.Name)

	//configure the pgpool includes all standby nodes AND the master node
	poolnames := make([]string, len(standbynodes)+1)

	i = 0
	for i = range standbynodes {
		poolnames[i] = standbynodes[i].Name + "." + domainname.Value
		i++
	}
	poolnames[i] = master.Name + "." + domainname.Value

	//generate pgpool.conf HOST_LIST
	data, err = template.Poolconf(poolnames)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:pgpool pgpool.conf generated")

	//write pgpool.conf to remote pool node
	_, err = cpmcontainerapi.RemoteWritefileClient(util.GetBase()+"/bin/"+"pgpool.conf", data, pgpoolNode.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	logit.Info.Println("configureCluster:pgpool pgpool.conf copied remotely")

	//generate pool_passwd
	data, err = template.Poolpasswd()
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:pgpool pool_passwd generated")

	//write pgpool.conf to remote pool node
	_, err = cpmcontainerapi.RemoteWritefileClient(util.GetBase()+"/bin/"+"pool_passwd", data, pgpoolNode.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	logit.Info.Println("configureCluster:pgpool pool_passwd copied remotely")

	//generate pool_hba.conf
	data, err = template.Poolhba()
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	logit.Info.Println("configureCluster:pgpool pool_hba generated")

	//write pgpool.conf to remote pool node
	_, err = cpmcontainerapi.RemoteWritefileClient(util.GetBase()+"/bin/"+"pool_hba.conf", data, pgpoolNode.Name)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}
	logit.Info.Println("configureCluster:pgpool pool_hba copied remotely")

	//start pgpool
	var startPoolResp cpmcontainerapi.StartPgpoolResponse
	startPoolResp, err = cpmcontainerapi.StartPgpoolClient(pgpoolNode.Name)
	if err != nil {
		logit.Error.Println("configureCluster: " + err.Error())
		return err
	}
	logit.Info.Println("configureCluster: pgpool startpgpool output was" + startPoolResp.Output)

	//finally, update the cluster to show that it is
	//initialized!
	cluster.Status = "initialized"
	err = admindb.UpdateCluster(dbConn, cluster)
	if err != nil {
		logit.Error.Println("configureCluster:" + err.Error())
		return err
	}

	return nil

}