func NewClusterChecker(uid string, cfg config) (*ClusterChecker, error) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Config{ Backend: store.Backend(cfg.storeBackend), Endpoints: cfg.storeEndpoints, CertFile: cfg.storeCertFile, KeyFile: cfg.storeKeyFile, CAFile: cfg.storeCAFile, SkipTLSVerify: cfg.storeSkipTlsVerify, }) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) return &ClusterChecker{ uid: uid, listenAddress: cfg.listenAddress, port: cfg.port, stopListening: cfg.stopListening, e: e, endPollonProxyCh: make(chan error), }, nil }
func configReplace(cmd *cobra.Command, args []string) { if crOpts.file == "" { die("no config file provided (--file/-f option)") } config := []byte{} var err error if crOpts.file == "-" { config, err = ioutil.ReadAll(os.Stdin) if err != nil { die("cannot read config file from stdin: %v", err) } } else { config, err = ioutil.ReadFile(crOpts.file) if err != nil { die("cannot read provided config file: %v", err) } } storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { die("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) if err = replaceConfig(e, config); err != nil { die("error: %v", err) } }
func spec(cmd *cobra.Command, args []string) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { die("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) cd, _, err := getClusterData(e) if err != nil { die("%v", err) } if cd.Cluster == nil { die("no cluster spec available") } if cd.Cluster.Spec == nil { die("no cluster spec available") } specj, err := json.MarshalIndent(cd.Cluster.Spec, "", "\t") if err != nil { die("failed to marshall spec: %v", err) } stdout("%s", specj) }
func configGet(cmd *cobra.Command, args []string) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { die("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) cfg, err := getConfig(e) if err != nil { die("error: %v", err) } if cfg == nil { stdout("config is not defined") os.Exit(0) } cfgj, err := json.MarshalIndent(cfg, "", "\t") if err != nil { die("failed to marshall config: %v", err) } stdout(string(cfgj)) }
func NewTestStore(dir string, a ...string) (*TestStore, error) { storeBackend := store.Backend(os.Getenv("STOLON_TEST_STORE_BACKEND")) switch storeBackend { case store.CONSUL: return NewTestConsul(dir, a...) case store.ETCD: return NewTestEtcd(dir, a...) } return nil, fmt.Errorf("wrong store backend") }
func NewSentinel(uid string, cfg *config, stop chan bool, end chan bool) (*Sentinel, error) { var initialClusterSpec *cluster.ClusterSpec if cfg.initialClusterSpecFile != "" { configData, err := ioutil.ReadFile(cfg.initialClusterSpecFile) if err != nil { return nil, fmt.Errorf("cannot read provided initial cluster config file: %v", err) } if err := json.Unmarshal(configData, &initialClusterSpec); err != nil { return nil, fmt.Errorf("cannot parse provided initial cluster config: %v", err) } log.Debug("initialClusterSpec dump", zap.String("initialClusterSpec", spew.Sdump(initialClusterSpec))) if err := initialClusterSpec.Validate(); err != nil { return nil, fmt.Errorf("invalid initial cluster: %v", err) } } storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Config{ Backend: store.Backend(cfg.storeBackend), Endpoints: cfg.storeEndpoints, CertFile: cfg.storeCertFile, KeyFile: cfg.storeKeyFile, CAFile: cfg.storeCAFile, SkipTLSVerify: cfg.storeSkipTlsVerify, }) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) candidate := leadership.NewCandidate(kvstore, filepath.Join(storePath, common.SentinelLeaderKey), uid, store.MinTTL) return &Sentinel{ uid: uid, cfg: cfg, e: e, candidate: candidate, leader: false, initialClusterSpec: initialClusterSpec, stop: stop, end: end, UIDFn: common.UID, // This is just to choose a pseudo random keeper so // use math.rand (no need for crypto.rand) without an // initial seed. RandFn: rand.Intn, sleepInterval: cluster.DefaultSleepInterval, requestTimeout: cluster.DefaultRequestTimeout, }, nil }
func NewStore() (*store.StoreManager, error) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Config{ Backend: store.Backend(cfg.storeBackend), Endpoints: cfg.storeEndpoints, CertFile: cfg.storeCertFile, KeyFile: cfg.storeKeyFile, CAFile: cfg.storeCAFile, SkipTLSVerify: cfg.storeSkipTlsVerify, }) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } return store.NewStoreManager(kvstore, storePath), nil }
func NewClusterChecker(id string, cfg config) (*ClusterChecker, error) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) return &ClusterChecker{ id: id, listenAddress: cfg.listenAddress, port: cfg.port, stopListening: cfg.stopListening, e: e, endPollonProxyCh: make(chan error), }, nil }
func getClusters(storeBasePath string) ([]string, error) { kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } clusters := []string{} pairs, err := kvstore.List(storeBasePath) if err != nil { if err != libkvstore.ErrKeyNotFound { return nil, err } return clusters, nil } for _, pair := range pairs { clusters = append(clusters, filepath.Base(pair.Key)) } sort.Strings(clusters) return clusters, nil }
func configPatch(cmd *cobra.Command, args []string) { if len(args) > 1 { die("too many arguments") } if cpOpts.file == "" && len(args) < 1 { die("no patch provided as argument and no patch file provided (--file/-f option)") } if cpOpts.file != "" && len(args) == 1 { die("only one of patch provided as argument or patch file must provided (--file/-f option)") } config := []byte{} if len(args) == 1 { config = []byte(args[0]) } else { var err error if cpOpts.file == "-" { config, err = ioutil.ReadAll(os.Stdin) if err != nil { die("cannot read config file from stdin: %v", err) } } else { config, err = ioutil.ReadFile(cpOpts.file) if err != nil { die("cannot read provided config file: %v", err) } } } storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { die("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) if err = patchConfig(e, config); err != nil { die("failed to patch config: %v", err) } }
func NewPostgresKeeper(id string, cfg config, stop chan bool, end chan error) (*PostgresKeeper, error) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) p := &PostgresKeeper{id: id, dataDir: cfg.dataDir, e: e, listenAddress: cfg.listenAddress, port: cfg.port, pgListenAddress: cfg.pgListenAddress, pgPort: cfg.pgPort, stop: stop, end: end, } return p, nil }
func initCluster(cmd *cobra.Command, args []string) { if len(args) > 1 { die("too many arguments") } data := []byte{} switch len(args) { case 1: data = []byte(args[0]) case 0: if initOpts.file != "" { var err error if initOpts.file == "-" { data, err = ioutil.ReadAll(os.Stdin) if err != nil { die("cannot read from stdin: %v", err) } } else { data, err = ioutil.ReadFile(initOpts.file) if err != nil { die("cannot read file: %v", err) } } } } storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { die("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) cd, _, err := e.GetClusterData() if err != nil { die("cannot get cluster data: %v", err) } if cd != nil { stdout("WARNING: The current cluster data will be removed") } stdout("WARNING: The databases managed by the keepers will be overwrited depending on the provided cluster spec.") accepted := true if !initOpts.forceYes { accepted, err = askConfirmation("Are you sure you want to continue? [yes/no] ") if err != nil { die("%v", err) } } if !accepted { stdout("exiting") os.Exit(0) } cd, _, err = e.GetClusterData() if err != nil { die("cannot get cluster data: %v", err) } var cs *cluster.ClusterSpec if len(data) == 0 { // Define a new cluster spec with initMode "new" cs = &cluster.ClusterSpec{} cs.InitMode = cluster.ClusterInitModeNew } else { if err := json.Unmarshal(data, &cs); err != nil { die("failed to unmarshal cluster spec: %v", err) } } cs.SetDefaults() if err := cs.Validate(); err != nil { die("invalid cluster spec: %v", err) } c := cluster.NewCluster(common.UID(), cs) cd = cluster.NewClusterData(c) // We ignore if cd has been modified between reading and writing if err := e.PutClusterData(cd); err != nil { die("cannot update cluster data: %v", err) } }
func update(cmd *cobra.Command, args []string) { if len(args) > 1 { die("too many arguments") } if updateOpts.file == "" && len(args) < 1 { die("no cluster spec provided as argument and no file provided (--file/-f option)") } if updateOpts.file != "" && len(args) == 1 { die("only one of cluster spec provided as argument or file must provided (--file/-f option)") } data := []byte{} if len(args) == 1 { data = []byte(args[0]) } else { var err error if updateOpts.file == "-" { data, err = ioutil.ReadAll(os.Stdin) if err != nil { die("cannot read from stdin: %v", err) } } else { data, err = ioutil.ReadFile(updateOpts.file) if err != nil { die("cannot read file: %v", err) } } } storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { die("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) retry := 0 for retry < maxRetries { cd, pair, err := getClusterData(e) if err != nil { die("%v", err) } if cd.Cluster == nil { die("no cluster spec available") } if cd.Cluster.Spec == nil { die("no cluster spec available") } var newcs *cluster.ClusterSpec if updateOpts.patch { newcs, err = patchClusterSpec(cd.Cluster.Spec, data) if err != nil { die("failed to patch cluster spec: %v", err) } } else { if err := json.Unmarshal(data, &newcs); err != nil { die("failed to unmarshal cluster spec: %v", err) } } newcs.SetDefaults() if err := cd.Cluster.UpdateSpec(newcs); err != nil { die("Cannot update cluster spec: %v", err) } // retry if cd has been modified between reading and writing _, err = e.AtomicPutClusterData(cd, pair) if err != nil { if err == libkvstore.ErrKeyModified { retry++ continue } die("cannot update cluster data: %v", err) } break } if retry == maxRetries { die("failed to update cluster data after %d retries", maxRetries) } }
func NewPostgresKeeper(cfg *config, stop chan bool, end chan error) (*PostgresKeeper, error) { storePath := filepath.Join(common.StoreBasePath, cfg.clusterName) kvstore, err := store.NewStore(store.Backend(cfg.storeBackend), cfg.storeEndpoints) if err != nil { return nil, fmt.Errorf("cannot create store: %v", err) } e := store.NewStoreManager(kvstore, storePath) p := &PostgresKeeper{ cfg: cfg, dataDir: cfg.dataDir, storeBackend: cfg.storeBackend, storeEndpoints: cfg.storeEndpoints, debug: cfg.debug, pgListenAddress: cfg.pgListenAddress, pgPort: cfg.pgPort, pgBinPath: cfg.pgBinPath, pgReplUsername: cfg.pgReplUsername, pgReplPassword: cfg.pgReplPassword, pgSUUsername: cfg.pgSUUsername, pgSUPassword: cfg.pgSUPassword, pgInitialSUUsername: cfg.pgInitialSUUsername, sleepInterval: cluster.DefaultSleepInterval, requestTimeout: cluster.DefaultRequestTimeout, keeperLocalState: &KeeperLocalState{}, dbLocalState: &DBLocalState{}, e: e, stop: stop, end: end, } err = p.loadKeeperLocalState() if err != nil && !os.IsNotExist(err) { return nil, fmt.Errorf("failed to load keeper local state file: %v", err) } if p.keeperLocalState.UID != "" && p.cfg.id != "" && p.keeperLocalState.UID != p.cfg.id { fmt.Printf("saved id %q differs from configuration id: %q\n", p.keeperLocalState.UID, cfg.id) os.Exit(1) } if p.keeperLocalState.UID == "" { p.keeperLocalState.UID = cfg.id if cfg.id == "" { p.keeperLocalState.UID = common.UID() log.Info("uid generated", zap.String("id", p.keeperLocalState.UID)) } if err = p.saveKeeperLocalState(); err != nil { fmt.Printf("error: %v\n", err) os.Exit(1) } } log.Info("keeper uid", zap.String("uid", p.keeperLocalState.UID)) err = p.loadDBLocalState() if err != nil && !os.IsNotExist(err) { return nil, fmt.Errorf("failed to load db local state file: %v", err) } return p, nil }