Beispiel #1
0
// Create Binding in the data store
func (b *Binding) Create() (err error) {
	log.Trace(fmt.Sprintf(`cfsb.Binding#Create(%s,%s) ... `, b.InstanceID, b.BindingID))

	instance, err := instances.FindByInstanceID(b.InstanceID)
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) instances.FindByInstanceID(%s) ! %s`, b.BindingID, b.InstanceID, err))
		return
	}

	dns, err := instance.ExternalDNS()
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) instance.ExternalDNS(%s) ! %s`, b.BindingID, b.InstanceID, err))
		return
	}
	// For now the crednetials are fixed, future feature is that we will be able to
	// create new users/credentials for each binding later on. Currently only
	// one set of credentials exists for each Instance.
	s := strings.Split(dns, ":")
	uri, err := instance.URI()
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) instance.URI(%s) ! %s`, b.BindingID, b.InstanceID, err))
		return
	}
	dsn, err := instance.DSN()
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) instance.DSN(%s) ! %s`, b.BindingID, b.InstanceID, err))
		return
	}
	jdbc, err := instance.JDBCURI()
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) instance.JDBCURI(%s) ! %s`, b.BindingID, b.InstanceID, err))
		return
	}

	b.Creds = &Credentials{
		InstanceID: b.InstanceID,
		BindingID:  b.BindingID,
		URI:        uri,
		DSN:        dsn,
		JDBCURI:    jdbc,
		Host:       s[0],
		Port:       s[1],
		UserName:   instance.User,
		Password:   instance.Pass,
		Database:   instance.Database,
	}

	p := pg.NewPG(`127.0.0.1`, pbPort, `rdpg`, `rdpg`, pgPass)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("cfsb.Binding#Create(%s) ! %s", b.BindingID, err))
		return
	}
	defer db.Close()

	err = b.Find()
	if err != nil {
		if err == sql.ErrNoRows { // Does not yet exist, insert the binding and it's credentials.
			sq := fmt.Sprintf(`INSERT INTO cfsb.bindings (instance_id,binding_id) VALUES (lower('%s'),lower('%s'));`, b.InstanceID, b.BindingID)
			log.Trace(fmt.Sprintf(`cfsb.Binding#Create() > %s`, sq))
			_, err = db.Exec(sq)
			if err != nil {
				log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) %s ! %s`, b.BindingID, sq, err))
			}
			err := b.Creds.Create()
			if err != nil {
				log.Error(fmt.Sprintf(`cfsb.Binding#Create(%s) b.Creds.Create() ! %s`, b.BindingID, err))
			}
		}
	} else { // Binding already exists, return existing binding and credentials.
		return
	}
	return
}
Beispiel #2
0
// InstanceHandler handles put and delete
// (PI) PUT /v2/service_instances/:id
// (RI) DELETE /v2/service_instances/:id
func InstanceHandler(w http.ResponseWriter, request *http.Request) {
	vars := mux.Vars(request)
	log.Trace(fmt.Sprintf("%s /v2/service_instances/:instance_id :: %+v", request.Method, vars))
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	switch request.Method {
	case "PUT":
		type instanceRequest struct {
			ServiceID      string `json:"service_id"`
			Plan           string `json:"plan_id"`
			OrganizationID string `json:"organization_guid"`
			SpaceID        string `json:"space_guid"`
		}
		ir := instanceRequest{}
		body, err := ioutil.ReadAll(request.Body)
		if err != nil {
			log.Error(fmt.Sprintf("%s /v2/service_instances/:instance_id %s", request.Method, err))
			writeJSONResponse(w, http.StatusInternalServerError, err.Error())
			return
		}
		err = json.Unmarshal(body, &ir)
		if err != nil {
			log.Error(fmt.Sprintf("%s /v2/service_instances/:instance_id ! %s", request.Method, err))
			writeJSONResponse(w, http.StatusInternalServerError, err.Error())
			return
		}
		instance, err := NewServiceInstance(
			vars["instance_id"],
			ir.ServiceID,
			ir.Plan,
			ir.OrganizationID,
			ir.SpaceID,
		)
		if err != nil {
			log.Error(fmt.Sprintf("%s /v2/service_instances/:instance_id ! %s", request.Method, err))
			writeJSONResponse(w, http.StatusInternalServerError, err.Error())
			return
		}
		err = instance.Provision()
		if err != nil {
			log.Error(fmt.Sprintf("%s /v2/service_instances/:instance_id ! %s", request.Method, err))
			writeJSONResponse(w, http.StatusInternalServerError, err.Error())
			return
		}

		msg := fmt.Sprintf("Provisioned Instance %s", instance.InstanceID)
		writeJSONResponse(w, http.StatusOK, msg)
		return
	case "DELETE":
		instance, err := instances.FindByInstanceID(vars["instance_id"])
		if err != nil {
			log.Error(fmt.Sprintf("%s /v2/service_instances/:instance_id ! %s", request.Method, err))
			msg := fmt.Sprintf("Could not find instance %s, perhaps it was already deleted?", vars["instance_id"])
			writeJSONResponse(w, http.StatusInternalServerError, msg)
			return
		}
		err = instance.Decommission()
		if err != nil {
			log.Error(fmt.Sprintf("%s /v2/service_instances/:instance_id %s", request.Method, err))
			writeJSONResponse(w, http.StatusInternalServerError, "There was an error decommissioning instance "+instance.InstanceID)
			return
		}
		writeJSONResponse(w, http.StatusOK, "Successfully Deprovisioned Instance "+instance.InstanceID)
	default:
		writeJSONResponse(w, http.StatusMethodNotAllowed, "Allowed Methods: PUT, DELETE")
	}
}
// TODO: This should be remove database
func (t *Task) RemoveDatabase(workRole string) (err error) {
	// For now we assume data is simply the database name.
	key := fmt.Sprintf("rdpg/%s/work/databases/remove", os.Getenv(`RDPGD_CLUSTER`))
	client, _ := consulapi.NewClient(consulapi.DefaultConfig())
	lock, err := client.LockKey(key)
	if err != nil {
		log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() Error aquiring lock ! %s", err))
		return
	}
	leaderCh, err := lock.Lock(nil)
	if err != nil {
		log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() Error aquiring lock ! %s", err))
		return
	}
	if leaderCh == nil {
		log.Trace(fmt.Sprintf("tasks.Task#RemoveDatabase() > Not Leader."))
		return
	}
	log.Trace(fmt.Sprintf("tasks.Task#RemoveDatabase() > Leader."))

	p := pg.NewPG(`127.0.0.1`, pbPort, `rdpg`, `rdpg`, pgPass)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() p.Connect() ! %s", err))
		return
	}
	ids := []string{}
	sq := fmt.Sprintf(`SELECT instance_id from cfsb.instances WHERE ineffective_at IS NOT NULL AND ineffective_at < CURRENT_TIMESTAMP AND decommissioned_at IS NULL`)
	err = db.Select(&ids, sq)
	if err != nil {
		log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() Querying for Databases to Cleanup ! %s", err))
	}
	db.Close()
	for _, id := range ids {
		db, err := p.Connect()
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() p.Connect() ! %s", err))
			return err
		}

		uri := "postgres://"
		b := bdr.NewBDR(uri, client)

		i, err := instances.FindByInstanceID(id)
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase(%s) FindingInstance(%s) ! %s", i.Database, i.InstanceID, err))
			db.Close()
			continue
		}

		err = b.DisableDatabase(i.Database)
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() DisableDatabase(%s) for %s ! %s", i.Database, i.InstanceID, err))
			db.Close()
			continue
		}

		err = b.BackupDatabase(i.Database)
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() BackupDatabase(%s) ! %s", i.Database, err))
			db.Close()
			continue
		}

		// Question, How do we "stop" the replication group before dropping the database?
		err = b.DropDatabase(i.Database)
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() DropDatabase(%s) for %s ! %s", i.Database, i.InstanceID, err))
			db.Close()
			continue
		}

		err = b.DropUser(i.User)
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() DropUser(%s) for %s ! %s", i.User, i.InstanceID, err))
			db.Close()
			continue
		}

		err = b.DropDatabase(i.Database)
		if err != nil {
			log.Error(fmt.Sprintf("tasks.Task#RemoveDatabase() DropDatabase(%s) for %s ! %s", i.Database, i.InstanceID, err))
			db.Close()
			continue
		}
	}
	db.Close()

	return
}