func (i *Instance) ExternalDNS() (dns string) { // TODO: Figure out where we'll store and retrieve the external DNS information r := rdpg.New() nodes := r.Nodes() // TODO: Import the external DNS host via env variable configuration. return nodes[0].Host + ":5432" }
func (c *Catalog) Fetch() (err error) { r := rdpg.New() err = r.OpenDB("rdpg") if err != nil { log.Error(fmt.Sprintf("Failed fetching catalog from database: %s", err)) return } db := r.DB err = db.Select(&c.Services, `SELECT service_id,name,description,bindable FROM cfsb.services;`) if err != nil { log.Error(fmt.Sprintf("Catalog#Fetch() selecting from cfsb.services %s", err.Error())) return } // TODO: Account for plans being associated with a service. for i, _ := range c.Services { service := &c.Services[i] err = db.Select(&service.Plans, `SELECT plan_id,name,description FROM cfsb.plans;`) if err != nil { log.Error(fmt.Sprintf("Catalog#Fetch() Service Plans %s", err.Error())) return } c.Services[i].Tags = []string{"rdpg", "postgresql"} // c.Services[i].Dashboard = DashboardClient{} } return }
func FindPlan(planId string) (plan *Plan, err error) { r := rdpg.New() r.OpenDB("rdpg") plan = &Plan{} sq := `SELECT id,name,description FROM cfsb.plans WHERE id=$1 LIMIT 1;` err = r.DB.Get(&plan, sq, planId) if err != nil { log.Error(fmt.Sprintf("cfsb.FindPlan(%s) %s", planId, err)) } r.DB.Close() return plan, err }
func FindInstance(instanceId string) (i *Instance, err error) { r := rdpg.New() in := Instance{} sq := `SELECT id, instance_id, service_id, plan_id, organization_id, space_id, dbname, uname, pass FROM cfsb.instances WHERE instance_id=lower($1) LIMIT 1;` r.OpenDB("rdpg") err = r.DB.Get(&in, sq, instanceId) if err != nil { // TODO: Change messaging if err is sql.NoRows then say couldn't find instance with instanceId log.Error(fmt.Sprintf("cfsb.FindInstance(%s) ! %s", instanceId, err)) } r.DB.Close() i = &in return }
func Instances() (si []Instance, err error) { r := rdpg.New() r.OpenDB("rdpg") si = []Instance{} // TODO: Move this into a versioned SQL Function. sq := `SELECT instance_id, service_id, plan_id, organization_id, space_id, dbname, uname, 'md5'||md5(cfsb.instances.pass||uname) as pass FROM cfsb.instances WHERE ineffective_at IS NULL; ` err = r.DB.Select(&si, sq) if err != nil { // TODO: Change messaging if err is sql.NoRows then say couldn't find instance with instanceId log.Error(fmt.Sprintf("cfsb.Instances() ! %s", err)) } r.DB.Close() return }
func FindBinding(bindingId string) (binding *Binding, err error) { r := rdpg.New() b := Binding{} sq := `SELECT id,instance_id, binding_id FROM cfsb.bindings WHERE binding_id=lower($1) LIMIT 1;` log.Trace(fmt.Sprintf(`cfsb.FindBinding(%s) > %s`, bindingId, sq)) r.OpenDB("rdpg") err = r.DB.Get(&b, sq, bindingId) if err != nil { // TODO: Change messaging if err is sql.NoRows then say couldn't find binding with bindingId log.Error(fmt.Sprintf("cfsb.FindBinding(%s) ! %s", bindingId, err)) } r.DB.Close() binding = &b return }
func RemoveBinding(bindingId string) (binding *Binding, err error) { binding, err = FindBinding(bindingId) if err != nil { log.Error(fmt.Sprintf(`cfsb.CreateBinding(%s) ! %s`, bindingId, err)) return } r := rdpg.New() sq := `UPDATE cfsb.bindings SET ineffective_at = CURRENT_TIMESTAMP WHERE binding_id = $1;` log.Trace(fmt.Sprintf(`cfsb.RemoveBinding(%s) > %s`, bindingId, sq)) r.OpenDB("rdpg") _, err = r.DB.Query(sq, bindingId) if err != nil { log.Error(fmt.Sprintf(`cfsb.CreateBinding(%s) ! %s`, bindingId, err)) } r.DB.Close() return }
func (i *Instance) Provision() (err error) { i.Pass = strings.ToLower(strings.Replace(rdpg.NewUUID().String(), "-", "", -1)) r := rdpg.New() // TODO: Alter this logic based on "plan" err = r.CreateUser(i.User, i.Pass) if err != nil { log.Error(fmt.Sprintf("Instance#Provision(%s) CreateUser(%s) ! %s", i.InstanceId, i.User, err)) return err } err = r.CreateDatabase(i.Database, i.User) if err != nil { log.Error(fmt.Sprintf("Instance#Provision(%s) CreateDatabase(%s,%s) ! %s", i.InstanceId, i.Database, i.User, err)) return err } err = r.CreateReplicationGroup(i.Database) if err != nil { log.Error(fmt.Sprintf("Instance#Provision(%s) CreateReplicationGroup(%s) ! %s", i.InstanceId, i.Database, err)) return err } r.OpenDB("rdpg") sq := `INSERT INTO cfsb.instances (instance_id, service_id, plan_id, organization_id, space_id, dbname, uname, pass) VALUES ($1,$2,$3,$4,$5,$6,$7,$8); ` _, err = r.DB.Query(sq, i.InstanceId, i.ServiceId, i.PlanId, i.OrganizationId, i.SpaceId, i.Database, i.User, i.Pass) if err != nil { log.Error(fmt.Sprintf(`Instance#Provision(%s) ! %s`, i.InstanceId, err)) } nodes := r.Nodes() for _, node := range nodes { err := node.AdminAPI("PUT", "services/pgbouncer/configure") if err != nil { log.Error(fmt.Sprintf(`Instance#Provision(%s) %s ! %s`, i.InstanceId, node.Host, err)) } } r.DB.Close() return nil }
func (i *Instance) Remove() (err error) { r := rdpg.New() r.OpenDB("rdpg") _, err = r.DB.Exec(`UPDATE cfsb.instances SET ineffective_at = CURRENT_TIMESTAMP WHERE id=$1`, i.Id) if err != nil { log.Error(fmt.Sprintf("Instance#Remove(%s) ! %s", i.InstanceId, err)) } time.Sleep(1) // Wait for the update to propigate to the other nodes. for _, node := range r.Nodes() { err := node.AdminAPI("PUT", "services/pgbouncer/configure") if err != nil { log.Error(fmt.Sprintf(`Instance#Provision(%s) %s ! %s`, i.InstanceId, node.Host, err)) } } r.DB.Close() return }
func Check(check string) (status int) { r := rdpg.New() err := r.OpenDB("rdpg") if err != nil { log.Error(fmt.Sprintf("Error opening ! %s", r.URI)) return http.StatusInternalServerError } switch check { case "ha_pb_pg": var numNodes int r.DB.Get(&numNodes, "SELECT count(node_name) FROM bdr.bdr_nodes;") if numNodes < 3 { return http.StatusInternalServerError } default: return http.StatusInternalServerError } return http.StatusOK }
func CreateBinding(instanceId, bindingId string) (binding *Binding, err error) { instance, err := FindInstance(instanceId) if err != nil { log.Error(fmt.Sprintf(`cfsb.CreateBinding(%s,%s) ! %s`, instanceId, bindingId, err)) return } binding = &Binding{BindingId: bindingId, InstanceId: instanceId} dns := instance.ExternalDNS() s := strings.Split(dns, ":") binding.Creds = Credentials{ URI: instance.URI(), DSN: instance.DSN(), JDBCURI: "jdbc:" + instance.URI(), Host: s[0], Port: s[1], UserName: instance.User, Password: instance.Pass, Database: instance.Database, } r := rdpg.New() r.OpenDB("rdpg") sq := `INSERT INTO cfsb.bindings (instance_id,binding_id) VALUES ($1,$2);` _, err = r.DB.Query(sq, binding.InstanceId, binding.BindingId) if err != nil { log.Error(fmt.Sprintf(`cfsb.CreateBinding(%s) ! %s`, bindingId, err)) } sq = `INSERT INTO cfsb.credentials (instance_id,binding_id,host,port,uname,pass,dbname) VALUES ($1,$2,$3,$4,$5,$6,$7);` _, err = r.DB.Query(sq, binding.InstanceId, binding.BindingId, binding.Creds.Host, binding.Creds.Port, binding.Creds.UserName, binding.Creds.Password, binding.Creds.Database) if err != nil { log.Error(fmt.Sprintf(`cfsb.CreateBinding(%s) ! %s`, bindingId, err)) } r.DB.Close() return }
func (s *Service) Configure() (err error) { log.Trace(fmt.Sprintf(`Service#Configure(%s)`, s.Name)) switch s.Name { case "consul": return errors.New(`Service#Configure("consul") is not yet implemented`) case "haproxy": header, err := ioutil.ReadFile(`/var/vcap/jobs/rdpg-agent/config/haproxy/haproxy.cfg.header`) if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } r := rdpg.New() nodes := r.Nodes() // TODO: 5432 & 6432 from environmental configuration. // TODO: Should this list come from active Consul registered nodes instead? footer := fmt.Sprintf(` frontend pgbdr_write_port bind 0.0.0.0:5432 mode tcp default_backend pgbdr_write_master backend pgbdr_write_master mode tcp server master %s:6432 check `, nodes[0].Host) hc := []string{string(header), footer} err = ioutil.WriteFile(`/var/vcap/jobs/haproxy/config/haproxy.cfg`, []byte(strings.Join(hc, "\n")), 0640) if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } cmd := exec.Command("/var/vcap/jobs/haproxy/bin/control", "reload") err = cmd.Run() if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } return errors.New(`Service#Configure("haproxy") is not yet implemented`) case "pgbouncer": instances, err := cfsb.Instances() if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } pgbConf, err := ioutil.ReadFile(`/var/vcap/jobs/rdpg-agent/config/pgbouncer/pgbouncer.ini`) if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } pgbUsers, err := ioutil.ReadFile(`/var/vcap/jobs/rdpg-agent/config/pgbouncer/users`) if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } pc := []string{string(pgbConf)} pu := []string{string(pgbUsers)} for _, i := range instances { // TODO: Fetch port from something like os.Getenv("PG_PORT") instead of hardcoding here. c := fmt.Sprintf(`%s = host=%s port=%s dbname=%s`, i.Database, "127.0.0.1", "7432", i.Database) pc = append(pc, c) u := fmt.Sprintf(`"%s" "%s"`, i.User, i.Pass) pu = append(pu, u) } pc = append(pc, "") pu = append(pu, "") err = ioutil.WriteFile(`/var/vcap/store/pgbouncer/config/pgbouncer.ini`, []byte(strings.Join(pc, "\n")), 0640) if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } err = ioutil.WriteFile(`/var/vcap/store/pgbouncer/config/users`, []byte(strings.Join(pu, "\n")), 0640) if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } cmd := exec.Command("/var/vcap/jobs/pgbouncer/bin/control", "reload") err = cmd.Run() if err != nil { log.Error(fmt.Sprintf("cfsb#Service.Configure(%s) ! %s", s.Name, err)) return err } case "pgbdr": return errors.New(`Service#Configure("pgbdr") is not yet implemented`) default: return errors.New(fmt.Sprintf(`Service#Configure("%s") is unknown.`, s.Name)) } return }