From 347fdf3e75891094c1b2ed5d22d20c6cc4c43440 Mon Sep 17 00:00:00 2001 From: RebeccaMahany Date: Mon, 12 Aug 2024 15:00:27 -0400 Subject: [PATCH 1/2] Return empty rows instead of error when db or object store doesn't exist --- ee/indexeddb/indexeddb.go | 13 ++++++++++--- ee/katc/table_test.go | 20 +++++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ee/indexeddb/indexeddb.go b/ee/indexeddb/indexeddb.go index 7449498e7..e2564b72e 100644 --- a/ee/indexeddb/indexeddb.go +++ b/ee/indexeddb/indexeddb.go @@ -11,6 +11,7 @@ import ( "path/filepath" "github.com/kolide/goleveldb/leveldb" + leveldberrors "github.com/kolide/goleveldb/leveldb/errors" "github.com/kolide/goleveldb/leveldb/opt" "github.com/kolide/launcher/ee/agent" ) @@ -41,6 +42,8 @@ func QueryIndexeddbObjectStore(dbLocation string, dbName string, objectStoreName // The copy was successful -- make sure we clean it up after we're done defer os.RemoveAll(tempDbCopyLocation) + objs := make([]map[string][]byte, 0) + opts := &opt.Options{ Comparer: indexeddbComparer, DisableSeeksCompaction: true, // no need to perform compaction @@ -64,7 +67,11 @@ func QueryIndexeddbObjectStore(dbLocation string, dbName string, objectStoreName } databaseIdRaw, err := db.Get(databaseNameKey, nil) if err != nil { - return nil, fmt.Errorf("querying for database id: %w", err) + // If the database doesn't exist, return an empty list of objects + if errors.Is(err, leveldberrors.ErrNotFound) { + return objs, nil + } + return nil, fmt.Errorf("querying for database id: %w", err) // TODO if leveldb: not found, return no rows? } databaseId, _ := binary.Uvarint(databaseIdRaw) @@ -88,14 +95,14 @@ func QueryIndexeddbObjectStore(dbLocation string, dbName string, objectStoreName } if objectStoreId == 0 { - return nil, errors.New("unable to get object store ID") + // If the object store doesn't exist, return an empty list of objects + return objs, nil } // Get the key prefix for all objects in this store. keyPrefix := objectDataKeyPrefix(databaseId, objectStoreId) // Now, we can read all records, keeping only the ones with our matching key prefix. - objs := make([]map[string][]byte, 0) iter := db.NewIterator(nil, nil) for iter.Next() { key := iter.Key() diff --git a/ee/katc/table_test.go b/ee/katc/table_test.go index ba77460f2..7c516c7c0 100644 --- a/ee/katc/table_test.go +++ b/ee/katc/table_test.go @@ -156,6 +156,7 @@ func TestQueryChromeIndexedDB(t *testing.T) { // indexeddb_leveldb.go and the ee/indexeddb package. for _, tt := range []struct { + testName string fileName string dbName string objStoreName string @@ -163,15 +164,32 @@ func TestQueryChromeIndexedDB(t *testing.T) { zipBytes []byte }{ { + testName: "file__0.indexeddb.leveldb.zip", fileName: "file__0.indexeddb.leveldb.zip", dbName: "launchertestdb", objStoreName: "launchertestobjstore", expectedRows: 2, zipBytes: basicChromeIndexeddb, }, + { + testName: "file__0.indexeddb.leveldb.zip -- db does not exist", + fileName: "file__0.indexeddb.leveldb.zip", + dbName: "not-the-correct-db-name", + objStoreName: "launchertestobjstore", + expectedRows: 0, + zipBytes: basicChromeIndexeddb, + }, + { + testName: "file__0.indexeddb.leveldb.zip -- object store does not exist", + fileName: "file__0.indexeddb.leveldb.zip", + dbName: "launchertestdb", + objStoreName: "not-the-correct-obj-store-name", + expectedRows: 0, + zipBytes: basicChromeIndexeddb, + }, } { tt := tt - t.Run(tt.fileName, func(t *testing.T) { + t.Run(tt.testName, func(t *testing.T) { t.Parallel() // Write zip bytes to file From e1054e78b3135333721536d8bc423c80eb142d67 Mon Sep 17 00:00:00 2001 From: RebeccaMahany Date: Mon, 12 Aug 2024 15:28:28 -0400 Subject: [PATCH 2/2] Remove TODO comment --- ee/indexeddb/indexeddb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/indexeddb/indexeddb.go b/ee/indexeddb/indexeddb.go index e2564b72e..d8810919f 100644 --- a/ee/indexeddb/indexeddb.go +++ b/ee/indexeddb/indexeddb.go @@ -71,7 +71,7 @@ func QueryIndexeddbObjectStore(dbLocation string, dbName string, objectStoreName if errors.Is(err, leveldberrors.ErrNotFound) { return objs, nil } - return nil, fmt.Errorf("querying for database id: %w", err) // TODO if leveldb: not found, return no rows? + return nil, fmt.Errorf("querying for database id: %w", err) } databaseId, _ := binary.Uvarint(databaseIdRaw)