Skip to content

Commit 79c6de3

Browse files
Mark vector search index index_subtype as backend_default (#5454)
## Changes - Add `index_subtype` as `backend_default` for vector search indexes and teach testserver to return a default value - Add `--unique` to `print_requests.py` so tests can choose to collapse subsequent GET requests (e.g. encountered during polling) ## Why - Grants test was failing with recreate ``` acceptance_test.go:939: Diff: --- bundle/resources/vector_search_indexes/grants/select/output.txt +++ /tmp/TestAcceptbundleresourcesvector_search_indexesgrantsselect1239696916/001/output.txt @@ -13,8 +13,11 @@ Deployment complete! >>> [CLI] bundle plan -Plan: 0 to add, 0 to change, 0 to delete, 3 unchanged +recreate vector_search_indexes.my_index +update vector_search_indexes.my_index.grants +Plan: 1 to add, 1 to change, 1 to delete, 1 unchanged + >>> [CLI] grants get table main.default.vs_index_[UNIQUE_NAME] { "privilege_assignments": [ ``` - `bundle/resources/vector_search_indexes/recreate/embedding_dimension/out.requests.create.direct.json` had an extra GET ``` --- bundle/resources/vector_search_indexes/recreate/embedding_dimension/out.requests.create.direct.json +++ /tmp/TestAcceptbundleresourcesvector_search_indexesrecreateembed3063347120/001/out.requests.create.direct.json @@ -21,3 +21,555 @@ "method": "GET", "path": "/api/2.0/vector-search/indexes/main.default.vs_index_[UNIQUE_NAME]" } +{ + "method": "GET", + "path": "/api/2.0/vector-search/indexes/main.default.vs_index_[UNIQUE_NAME]" +} ``` ## Tests Reverted the `resources.yml` change and reran `grants/select`: ``` >>> [CLI] bundle plan -Plan: 0 to add, 0 to change, 0 to delete, 3 unchanged +recreate vector_search_indexes.my_index +update vector_search_indexes.my_index.grants + +Plan: 1 to add, 1 to change, 1 to delete, 1 unchanged ```
1 parent 5dcec26 commit 79c6de3

7 files changed

Lines changed: 55 additions & 5 deletions

File tree

NEXT_CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Bundles
1010
* Set the default `data_security_mode` to `DATA_SECURITY_MODE_AUTO` in bundle templates ([#5452](https://github.com/databricks/cli/pull/5452)).
11+
* Mark vector search index index_subtype as backend_default to prevent drift after deployment ([#5454](https://github.com/databricks/cli/pull/5454)).
1112

1213
### Dependency updates
1314

acceptance/bin/print_requests.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@
5656
>>> # Test positive + negative filters (AND logic)
5757
>>> test(test_requests, ["//api", "^/jobs"], False, False)
5858
R4 POST
59+
60+
>>> # --unique collapses consecutive duplicate requests (like uniq), e.g. repeated GET polls
61+
>>> dup_requests = [
62+
... {"method": "POST", "path": "/api/2.0/idx", "body": {"n": 1}},
63+
... {"method": "GET", "path": "/api/2.0/idx"},
64+
... {"method": "GET", "path": "/api/2.0/idx"},
65+
... ]
66+
>>> [x["method"] for x in filter_requests(dup_requests, ["//idx"], True, False, unique=True)]
67+
['POST', 'GET']
68+
69+
>>> # Only consecutive duplicates collapse; a repeat after another request is kept
70+
>>> seq = [
71+
... {"method": "GET", "path": "/api/2.0/idx"},
72+
... {"method": "DELETE", "path": "/api/2.0/idx"},
73+
... {"method": "GET", "path": "/api/2.0/idx"},
74+
... {"method": "GET", "path": "/api/2.0/idx"},
75+
... ]
76+
>>> [x["method"] for x in filter_requests(seq, ["//idx"], True, False, unique=True)]
77+
['GET', 'DELETE', 'GET']
5978
"""
6079

6180
import os
@@ -104,7 +123,7 @@ def read_json_many(s):
104123
assert result == [{"method": "GET"}, {"method": "POST"}], result
105124

106125

107-
def filter_requests(requests, path_filters, include_get, should_sort):
126+
def filter_requests(requests, path_filters, include_get, should_sort, unique=False):
108127
"""Filter requests based on method and path filters."""
109128
positive_filters = []
110129
negative_filters = []
@@ -145,6 +164,13 @@ def filter_requests(requests, path_filters, include_get, should_sort):
145164
if should_sort:
146165
filtered_requests.sort(key=str)
147166

167+
if unique:
168+
deduped = []
169+
for req in filtered_requests:
170+
if not deduped or deduped[-1] != req:
171+
deduped.append(req)
172+
filtered_requests = deduped
173+
148174
return filtered_requests
149175

150176

@@ -155,6 +181,11 @@ def main():
155181
parser.add_argument("--get", action="store_true", help="Include GET requests (excluded by default)")
156182
parser.add_argument("--keep", action="store_true", help="Keep out.requests.json file after processing")
157183
parser.add_argument("--sort", action="store_true", help="Sort requests before output")
184+
parser.add_argument(
185+
"--unique",
186+
action="store_true",
187+
help="Collapse consecutive duplicate requests (like uniq), e.g. repeated GET polls",
188+
)
158189
parser.add_argument("--oneline", action="store_true", help="Print output with one request per line")
159190
parser.add_argument("--fname", default="out.requests.txt")
160191
args = parser.parse_args()
@@ -175,7 +206,7 @@ def main():
175206
return
176207

177208
requests = read_json_many(data)
178-
filtered_requests = filter_requests(requests, args.path_filters, args.get, args.sort)
209+
filtered_requests = filter_requests(requests, args.path_filters, args.get, args.sort, args.unique)
179210
if args.verbose:
180211
print(
181212
f"Read {len(data)} chars, {len(requests)} requests, {len(filtered_requests)} after filtering",

acceptance/bundle/resources/vector_search_indexes/recreate/embedding_dimension/output.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Deploying resources...
66
Updating deployment state...
77
Deployment complete!
88

9-
>>> print_requests.py --get //vector-search/indexes
9+
>>> print_requests.py --get --unique //vector-search/indexes
1010

1111
=== Change embedding_dimension (should trigger recreation)
1212
>>> update_file.py databricks.yml embedding_dimension: 768 embedding_dimension: 384
@@ -27,7 +27,7 @@ Deploying resources...
2727
Updating deployment state...
2828
Deployment complete!
2929

30-
>>> print_requests.py --get //vector-search/indexes
30+
>>> print_requests.py --get --unique //vector-search/indexes
3131

3232
>>> [CLI] vector-search-indexes get-index main.default.vs_index_[UNIQUE_NAME]
3333
{

acceptance/bundle/resources/vector_search_indexes/recreate/embedding_dimension/script

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ print_requests() {
1212
# without that, removing the wait would silently still pass against the
1313
# testserver (which finishes deletion synchronously) — the GET in the log
1414
# is the assertion that the wait actually fired.
15-
trace print_requests.py --get '//vector-search/indexes' > out.requests.${name}.$DATABRICKS_BUNDLE_ENGINE.json
15+
# --unique collapses the repeated identical poll GETs (one on the testserver,
16+
# many on a real workspace that provisions asynchronously) to a stable count.
17+
trace print_requests.py --get --unique '//vector-search/indexes' > out.requests.${name}.$DATABRICKS_BUNDLE_ENGINE.json
1618
rm -f out.requests.txt
1719
}
1820

acceptance/bundle/resources/vector_search_indexes/recreate/with_endpoint/output.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Plan: 1 to add, 0 to change, 1 to delete, 1 unchanged
7373
},
7474
"endpoint_name": "vs-endpoint-[UNIQUE_NAME]",
7575
"endpoint_uuid": "[UUID]",
76+
"index_subtype": "HYBRID",
7677
"index_type": "DIRECT_ACCESS",
7778
"name": "main.default.vs_index_[UNIQUE_NAME]",
7879
"primary_key": "id",
@@ -86,6 +87,11 @@ Plan: 1 to add, 0 to change, 1 to delete, 1 unchanged
8687
"reason": "state-only field",
8788
"old": "[UUID]",
8889
"remote": "[UUID]"
90+
},
91+
"index_subtype": {
92+
"action": "skip",
93+
"reason": "backend_default",
94+
"remote": "HYBRID"
8995
}
9096
}
9197
}

bundle/direct/dresources/resources.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,3 +608,6 @@ resources:
608608
reason: immutable
609609
- field: direct_access_index_spec
610610
reason: immutable
611+
backend_defaults:
612+
# The Vector Search API assigns index_subtype when the config omits it
613+
- field: index_subtype

libs/testserver/vector_search_indexes.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,18 @@ func (s *FakeWorkspace) VectorSearchIndexCreate(req Request) Response {
6464
}
6565
}
6666

67+
// The backend assigns index_subtype when the request omits it (HYBRID by default)
68+
indexSubtype := createReq.IndexSubtype
69+
if indexSubtype == "" {
70+
indexSubtype = vectorsearch.IndexSubtypeHybrid
71+
}
72+
6773
index := fakeVectorSearchIndex{
6874
VectorIndex: vectorsearch.VectorIndex{
6975
Creator: s.CurrentUser().UserName,
7076
EndpointName: createReq.EndpointName,
7177
IndexType: createReq.IndexType,
78+
IndexSubtype: indexSubtype,
7279
Name: createReq.Name,
7380
PrimaryKey: createReq.PrimaryKey,
7481
DeltaSyncIndexSpec: remapDeltaSyncSpec(createReq.DeltaSyncIndexSpec),

0 commit comments

Comments
 (0)