func loadRestoreConfig(planName string) restoreconfig.Config { configPath := filepath.Join("assets", "restore-"+planName+".yml") config, err := restoreconfig.Load(configPath) Expect(err).ToNot(HaveOccurred()) return config }
func main() { fmt.Println("Starting redis restore") if len(os.Args) != 3 { log.Fatalf("usage: restore <instance_id> <rdb_path>") } instanceID := os.Args[1] rdbPath := os.Args[2] logger := lager.NewLogger("redis-restore") logger.RegisterSink(lager.NewWriterSink(os.Stdout, lager.DEBUG)) logger.RegisterSink(lager.NewWriterSink(os.Stderr, lager.ERROR)) startStep("Loading config") config, err := restoreconfig.Load(restoreConfigPath()) if err != nil { finishStepFatal("Could not load config") } finishStep("OK") monitExecutablePath := config.MonitExecutablePath instanceDirPath := config.InstanceDataDir(instanceID) startStep("Checking instance directory and backup file") if _, err := os.Stat(instanceDirPath); os.IsNotExist(err) { finishStepFatal("Instance not found") } if _, err := os.Stat(rdbPath); os.IsNotExist(err) { log.Fatalf("RDB file not found") } finishStep("OK") commandRunner := system.OSCommandRunner{ Logger: logger, } startStep("Disabling Redis process watcher") if config.DedicatedInstance { finishStep("Skipped") } else { err = stopViaMonit(monitExecutablePath, "process-watcher") if err != nil { finishStep("ERROR") logger.Fatal("stop-process-watcher", err) } finishStep("OK") } processKiller := &process.ProcessKiller{} processController := &redis.OSProcessController{ CommandRunner: commandRunner, InstanceInformer: &config, Logger: logger, ProcessChecker: &process.ProcessChecker{}, ProcessKiller: processKiller, PingFunc: redis.PingServer, WaitUntilConnectableFunc: availability.Check, RedisServerExecutablePath: config.RedisServerExecutablePath, } instance := &redis.Instance{ID: instanceID, Host: "localhost", Port: 6379} pidfilePath := config.InstancePidFilePath(instanceID) startStep("Stopping Redis") if config.DedicatedInstance { if err = unmonit(monitExecutablePath, "redis"); err == nil { err = processKiller.KillProvidedPID(redisPIDProvider(instanceDirPath)) } } else { err = processController.Kill(instance) } if err != nil { finishStep("ERROR") logger.Fatal("killing-redis", err) } finishStep("OK") startStep("Copying backup file to instance directory") err = copyRdbFileIntoInstance(rdbPath, instanceDirPath) if err != nil { finishStep("ERROR") logger.Fatal("copy-rdb", err) } finishStep("OK") startStep("Starting Redis from backup file") err = processController.StartAndWaitUntilReadyWithConfig( instance, []string{ "--pidfile", pidfilePath, "--daemonize", "yes", "--dir", instanceDirPath, "--bind", "127.0.0.1", }, time.Duration(config.StartRedisTimeoutSeconds)*time.Second, ) if err != nil { finishStep("ERROR") logger.Fatal("starting-redis", err) } finishStep("OK") startStep("Waiting for redis to finish loading data into memory") client, err := client.Connect( client.Host(instance.Host), client.Port(instance.Port), ) if err != nil { finishStep("ERROR") logger.Fatal("connecting-to-redis", err) } err = client.WaitUntilRedisNotLoading(config.StartRedisTimeoutSeconds * 1000) if err != nil { finishStep("ERROR") logger.Fatal("starting-redis", err) } finishStep("OK") startStep("Enabling appendonly mode") err = client.EnableAOF() if err != nil { finishStep("ERROR") logger.Fatal("enabling-aof", err) } finishStep("OK") startStep("Waiting for appendonly rewrite to finish") for { aofRewriteInProgress, err := client.InfoField("aof_rewrite_in_progress") if err != nil { finishStep("ERROR") logger.Fatal("querying-aof-progress", err) } if aofRewriteInProgress == "0" { break } time.Sleep(time.Millisecond * aofRewriteInProgressCheckIntervalMilliseconds) } aofRewriteStatus, err := client.InfoField("aof_last_bgrewrite_status") if err != nil { logger.Fatal("getting-aof-write-status", err) } if aofRewriteStatus != "ok" { logger.Fatal( "verifying-aof-write-status", fmt.Errorf("Invalid AOF write status: %s", aofRewriteStatus), ) } finishStep("OK") startStep("Stopping Redis") err = processController.Kill(instance) if err != nil { finishStep("ERROR") logger.Fatal("killing-redis", err) } finishStep("OK") startStep("Setting correct permissions on appendonly file") aofPath := path.Join(instanceDirPath, "appendonly.aof") err = chownAof("vcap", aofPath) if err != nil { finishStep("ERROR") logger.Fatal("chown-aof", err) } finishStep("OK") startStep("Restarting Redis process watcher/redis") if config.DedicatedInstance { err = startViaMonit(monitExecutablePath, "redis") } else { err = startViaMonit(monitExecutablePath, "process-watcher") } if err != nil { finishStep("ERROR") logger.Fatal("start redis/process watcher", err) } finishStep("OK") fmt.Println("Restore completed successfully") }
"os" "path" "github.com/pivotal-cf/cf-redis-broker/restoreconfig" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Config", func() { var restoreConfig restoreconfig.Config Context("Loads values from restore_config.yml", func() { BeforeEach(func() { var err error restoreConfig, err = restoreconfig.Load(path.Join("assets", "restore-dedicated.yml")) Expect(err).ToNot(HaveOccurred()) }) It("Reads the monit executable", func() { Expect(restoreConfig.MonitExecutablePath).To(Equal("/path/to/monit/file")) }) It("Reads the redis data directory", func() { Expect(restoreConfig.RedisDataDirectory).To(Equal("/tmp/redis/data")) }) It("Reads the pidfile directory", func() { Expect(restoreConfig.PidfileDirectory).To(Equal("/tmp/pidfiles")) })