// setup continuous replication between all pods in couchdb cluster // first it will cancel any replication for all pods // then it will reinit circle continuous replication between all pods // requirement -> replicas > 1 !! // @param cluster - CouchdbCluster struct - cluster where setup replication func (cluster *CouchdbCluster) SetupReplication(databases []string) error { DebugLog("couchdb_control: setup: _replication: Replication setup for all PODS, dbs to replicate:") DebugLog(databases) // check fi all pods are ready and in running state err := cluster.CheckAllCouchdbPods() if err != nil { ErrorLog("couchdb_control: setup_replication: check all pods error") return err } // create couchdb admin credentials credentials := couch.NewCredentials(cluster.Username, cluster.Password) // get all pods podSvcList, err := cluster.GetAllPodServices() if err != nil { ErrorLog("couchdb_control: setup_replication: check all pods error") return err } podSvcs := *podSvcList DebugLog("couchdb_control: setup_replication: interate throught all pod services") // iterate through all pods for i := 0; i < len(podSvcs); i++ { // index of next pod j := (i + 1) % len(podSvcs) DebugLog("couchdb_control: setup replication: pod: " + podSvcs[i].Name + "," + podSvcs[i].Spec.ClusterIP) // primary - replicate FROM server1 := couch.NewServer("http://"+podSvcs[i].Spec.ClusterIP+":"+COUCHDB_PORT_STRING, credentials) // check server1 if err := CheckServer(server1, MAX_RETRIES, RETRY_WAIT_TIME); err != nil { // failed to connect to server after all retries, fail replication ErrorLog("couchdb_control: setupReplication: failed to connect to server1, pod:" + podSvcs[i].Name) ErrorLog(err) return err } // secondary - replicate TO server2 := couch.NewServer("http://"+podSvcs[j].Spec.ClusterIP+":"+COUCHDB_PORT_STRING, credentials) if err := CheckServer(server2, MAX_RETRIES, RETRY_WAIT_TIME); err != nil { // failed to connect to server after all retries, fail replication ErrorLog("couchdb_control: setupReplication: failed to connect to server2, pod:" + podSvcs[j].Name) ErrorLog(err) return err } // set replication between two pods for all listed databases for _, db := range databases { // db1 server1 db1 := server1.Database(db) db1.Create() // db1 server2 db2 := server2.Database(db) db2.Create() // REPLICATION CHOOSE ONLY ONE // 1) using _replicate // 2) using _replicator // replication struct, use headless service name for replication target replicator := CouchdbReplicator{Id: "replicate_" + db, Continuous: true, Source: db1.URL(), Target: "http://" + cluster.Username + ":" + cluster.Password + "@" + podSvcs[j].Spec.ClusterIP + ":" + COUCHDB_PORT_STRING + "/" + db} // 1) // continuous replication , saves to "_replicate" // limits: anything in _replication is lost when db is restarted // DELETE old replication, if any found // cannot by done without saving information or without server restart // restart server1 and wait until its online, should be fast //couch.Do(server1.URL()+"/_restart", METHOD_POST, server1.Cred(), nil, nil) //CheckServer(server1, MAX_RETRIES, RETRY_WAIT_TIME) // setup replication //couch.Do(server1.URL()+"/_replicate", METHOD_POST, server1.Cred(), &replicator, nil) // 2) // continuous replication via "_replicator" // this replication survive restarts but fails replicate database "_users" if db == "_users" { // there is a bug with _replicator and db _users, we cannot replicate this DB continue } // delete old replication, if any found // get old replicator record oldReplicator := CouchdbReplicator{} couch.Do(server1.URL()+"/_replicator/"+"replicate_"+db, METHOD_GET, server1.Cred(), nil, &oldReplicator) //DebugLog(oldReplicator.Rev) // if valid replicator record found, delete it if oldReplicator.Rev != "" { server1.Database("_replicator").Delete("replicate_"+db, oldReplicator.Rev) } // setup new replication in _replicator db couch.Do(server1.URL()+"/_replicator", METHOD_POST, server1.Cred(), &replicator, nil) } } //DebugLog("finished replication configuration") // no errors return nil }
func server() *couch.Server { return couch.NewServer(testHost, testCred) }