diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f8c1fb2ec..ee328a10e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ The stress tool `influx_stress` will be removed in a subsequent release. We reco - [#7563](https://github.com/influxdata/influxdb/issues/7563): RP should not allow `INF` or `0` as a shard duration. - [#7585](https://github.com/influxdata/influxdb/pull/7585): Return Error instead of panic when decoding point values. - [#7812](https://github.com/influxdata/influxdb/issues/7812): Fix slice out of bounds panic when pruning shard groups. Thanks @vladlopes +- [#7822](https://github.com/influxdata/influxdb/issues/7822): Drop database will delete /influxdb/data directory ## v1.1.1 [2016-12-06] diff --git a/coordinator/statement_executor.go b/coordinator/statement_executor.go index 20676e80b83..4d0f54a3699 100644 --- a/coordinator/statement_executor.go +++ b/coordinator/statement_executor.go @@ -305,6 +305,10 @@ func (e *StatementExecutor) executeDropContinuousQueryStatement(q *influxql.Drop // It does not return an error if the database was not found on any of // the nodes, or in the Meta store. func (e *StatementExecutor) executeDropDatabaseStatement(stmt *influxql.DropDatabaseStatement) error { + if e.MetaClient.Database(stmt.Name) == nil { + return nil + } + // Locally delete the datababse. if err := e.TSDBStore.DeleteDatabase(stmt.Name); err != nil { return err @@ -348,6 +352,16 @@ func (e *StatementExecutor) executeDropShardStatement(stmt *influxql.DropShardSt } func (e *StatementExecutor) executeDropRetentionPolicyStatement(stmt *influxql.DropRetentionPolicyStatement) error { + + dbi := e.MetaClient.Database(stmt.Database) + if dbi == nil { + return nil + } + + if dbi.RetentionPolicy(stmt.Name) == nil { + return nil + } + // Locally drop the retention policy. if err := e.TSDBStore.DeleteRetentionPolicy(stmt.Database, stmt.Name); err != nil { return err diff --git a/tsdb/store.go b/tsdb/store.go index 267ca51b414..9f4e1a31a24 100644 --- a/tsdb/store.go +++ b/tsdb/store.go @@ -387,6 +387,11 @@ func (s *Store) DeleteShard(shardID uint64) error { // DeleteDatabase will close all shards associated with a database and remove the directory and files from disk. func (s *Store) DeleteDatabase(name string) error { s.mu.RLock() + if s.databaseIndexes[name] == nil { + s.mu.RUnlock() + // no files locally, so nothing to do + return nil + } shards := s.filterShards(func(sh *Shard) bool { return sh.database == name }) @@ -402,7 +407,15 @@ func (s *Store) DeleteDatabase(name string) error { return err } - if err := os.RemoveAll(filepath.Join(s.path, name)); err != nil { + dbPath := filepath.Clean(filepath.Join(s.path, name)) + + // extra sanity check to make sure that even if someone named their database "../.." + // that we don't delete everything because of it, they'll just have extra files forever + if filepath.Clean(s.path) != filepath.Dir(dbPath) { + return fmt.Errorf("invalid database directory location for database '%s': %s", name, dbPath) + } + + if err := os.RemoveAll(dbPath); err != nil { return err } if err := os.RemoveAll(filepath.Join(s.EngineOptions.Config.WALDir, name)); err != nil { @@ -424,6 +437,10 @@ func (s *Store) DeleteDatabase(name string) error { // both the DB and WAL, and remove all shard files from disk. func (s *Store) DeleteRetentionPolicy(database, name string) error { s.mu.RLock() + if s.databaseIndexes[database] == nil { + // unknown database, nothing to do + return nil + } shards := s.filterShards(func(sh *Shard) bool { return sh.database == database && sh.retentionPolicy == name }) @@ -441,6 +458,13 @@ func (s *Store) DeleteRetentionPolicy(database, name string) error { return err } + rpPath := filepath.Clean(filepath.Join(s.path, database, name)) + + // ensure Store's path is the grandparent of the retention policy + if filepath.Clean(s.path) != filepath.Dir(filepath.Dir(rpPath)) { + return fmt.Errorf("invalid path for database '%s', retention policy '%s': %s", database, name, rpPath) + } + // Remove the rentention policy folder. if err := os.RemoveAll(filepath.Join(s.path, database, name)); err != nil { return err