lkr-dev-cli 0.0.30__tar.gz → 0.0.31__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lkr_dev_cli-0.0.31/.github/workflows/test-dependencies.yml +34 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/Dockerfile +1 -1
- lkr_dev_cli-0.0.31/Makefile +7 -0
- lkr_dev_cli-0.0.30/README.md → lkr_dev_cli-0.0.31/PKG-INFO +117 -6
- lkr_dev_cli-0.0.30/PKG-INFO → lkr_dev_cli-0.0.31/README.md +86 -28
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/tools/classes.py +5 -4
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/tools/main.py +1 -1
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/pyproject.toml +18 -3
- lkr_dev_cli-0.0.31/tests/TESTING.md +96 -0
- lkr_dev_cli-0.0.31/tests/test_dependency_resolution.py +180 -0
- lkr_dev_cli-0.0.31/tests/test_deps.sh +119 -0
- lkr_dev_cli-0.0.31/uv.lock +954 -0
- lkr_dev_cli-0.0.30/Makefile +0 -4
- lkr_dev_cli-0.0.30/uv.lock +0 -842
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/.github/workflows/release.yml +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/.gitignore +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/.python-version +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/.vscode/launch.json +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/.vscode/settings.json +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/LICENSE +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/cloudbuild.yaml +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/__init__.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/auth/__init__.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/auth/main.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/auth/oauth.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/auth_service.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/classes.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/constants.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/custom_types.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/exceptions.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/logger.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/main.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/mcp/classes.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/mcp/main.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/mcp/utils.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/observability/classes.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/observability/embed_container.html +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/observability/main.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr/observability/utils.py +0 -0
- {lkr_dev_cli-0.0.30 → lkr_dev_cli-0.0.31}/lkr.md +0 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Test Dependency Resolution
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main, develop ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ main, develop ]
|
8
|
+
workflow_dispatch:
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
test-dependencies:
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- name: Checkout code
|
16
|
+
uses: actions/checkout@v4
|
17
|
+
|
18
|
+
- name: Setup Python
|
19
|
+
uses: actions/setup-python@v4
|
20
|
+
with:
|
21
|
+
python-version: '3.12'
|
22
|
+
|
23
|
+
- name: Install uv
|
24
|
+
uses: astral-sh/setup-uv@v2
|
25
|
+
with:
|
26
|
+
version: latest
|
27
|
+
|
28
|
+
- name: Install dependencies
|
29
|
+
run: |
|
30
|
+
uv sync --extra all
|
31
|
+
|
32
|
+
- name: Run with pytest
|
33
|
+
run: |
|
34
|
+
uv run pytest tests/test_dependency_resolution.py -v
|
@@ -1,3 +1,34 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: lkr-dev-cli
|
3
|
+
Version: 0.0.31
|
4
|
+
Summary: lkr: a command line interface for looker
|
5
|
+
Author: bwebs
|
6
|
+
License-Expression: MIT
|
7
|
+
License-File: LICENSE
|
8
|
+
Requires-Python: >=3.12
|
9
|
+
Requires-Dist: cryptography>=42.0.0
|
10
|
+
Requires-Dist: looker-sdk>=25.4.0
|
11
|
+
Requires-Dist: pydantic>=2.11.4
|
12
|
+
Requires-Dist: pydash>=8.0.5
|
13
|
+
Requires-Dist: questionary>=2.1.0
|
14
|
+
Requires-Dist: requests>=2.31.0
|
15
|
+
Requires-Dist: structlog>=25.3.0
|
16
|
+
Requires-Dist: typer>=0.15.2
|
17
|
+
Provides-Extra: all
|
18
|
+
Requires-Dist: duckdb>=1.2.2; extra == 'all'
|
19
|
+
Requires-Dist: fastapi>=0.115.12; extra == 'all'
|
20
|
+
Requires-Dist: mcp[cli]>=1.9.2; extra == 'all'
|
21
|
+
Requires-Dist: selenium>=4.32.0; extra == 'all'
|
22
|
+
Provides-Extra: embed-observability
|
23
|
+
Requires-Dist: fastapi>=0.115.12; extra == 'embed-observability'
|
24
|
+
Requires-Dist: selenium>=4.32.0; extra == 'embed-observability'
|
25
|
+
Provides-Extra: mcp
|
26
|
+
Requires-Dist: duckdb>=1.2.2; extra == 'mcp'
|
27
|
+
Requires-Dist: mcp[cli]>=1.9.2; extra == 'mcp'
|
28
|
+
Provides-Extra: user-attribute-updater
|
29
|
+
Requires-Dist: fastapi>=0.115.12; extra == 'user-attribute-updater'
|
30
|
+
Description-Content-Type: text/markdown
|
31
|
+
|
1
32
|
# lkr cli
|
2
33
|
|
3
34
|
The `lkr` cli is a tool for interacting with Looker. It combines Looker's SDK and customer logic to interact with Looker in meaninful ways. For a full list of commands, see the full [cli docs](./lkr.md)
|
@@ -192,10 +223,13 @@ This can also be used to stress test your Looker environment as it serves an API
|
|
192
223
|
## User Attribute Updater (OIDC Token)
|
193
224
|
|
194
225
|
1. Create a new cloud run using the `lkr-cli` public docker image `us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest`
|
195
|
-
2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings.
|
196
|
-
3.
|
197
|
-
|
198
|
-
|
226
|
+
2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings. See example [`gcloud` command](#example-gcloud-command)
|
227
|
+
3. For the command and arguments use:
|
228
|
+
- command: `lkr`
|
229
|
+
- args: `tools` `user-attribute-updater`
|
230
|
+
4. Deploy the cloud run
|
231
|
+
5. Retrieve the URL of the cloud run
|
232
|
+
6. Create the user attribute
|
199
233
|
- Name: cloud_run_access_token
|
200
234
|
- Data Type: String
|
201
235
|
- User Access: None
|
@@ -228,6 +262,23 @@ This can also be used to stress test your Looker environment as it serves an API
|
|
228
262
|
9. Check the logs of the cloud run to see if there was a 200 response
|
229
263
|
|
230
264
|
|
265
|
+
### Example `gcloud` command
|
266
|
+
```bash
|
267
|
+
export REGION=<your region>
|
268
|
+
export PROJECT=<your project id>
|
269
|
+
|
270
|
+
gcloud run deploy lkr-access-token-updater \
|
271
|
+
--image us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest \
|
272
|
+
--command lkr \
|
273
|
+
--args tools,user-attribute-updater \
|
274
|
+
--platform managed \
|
275
|
+
--region $REGION \
|
276
|
+
--project $PROJECT \
|
277
|
+
--cpu 1 \
|
278
|
+
--memory 2Gi \
|
279
|
+
--set-env-vars LOOKERSDK_CLIENT_ID=<your client id>,LOOKERSDK_CLIENT_SECRET=<your client secret>,LOOKERSDK_BASE_URL=<your instance url>,LOOKER_WHITELISTED_BASE_URLS=<your instance url>
|
280
|
+
```
|
281
|
+
|
231
282
|
## UserAttributeUpdater `lkr-dev-cli`
|
232
283
|
|
233
284
|
Exported from the `lkr-dev-cli` package is the `UserAttributeUpdater` pydantic class. This class has all the necessary logic to update a user attribute value.
|
@@ -279,12 +330,12 @@ from lkr import UserAttributeUpdater
|
|
279
330
|
def request_authorization(request: Request):
|
280
331
|
body = await request.json()
|
281
332
|
updater = UserAttributeUpdater.model_validate(body)
|
282
|
-
updater.get_request_authorization_for_value(request)
|
333
|
+
updater.get_request_authorization_for_value(request.headers.items())
|
283
334
|
updater.update_user_attribute_value()
|
284
335
|
|
285
336
|
@app.post("/as_body")
|
286
337
|
def as_body(request: Request, body: UserAttributeUpdater):
|
287
|
-
body.get_request_authorization_for_value(request)
|
338
|
+
body.get_request_authorization_for_value(request.headers.items())
|
288
339
|
body.update_user_attribute_value()
|
289
340
|
|
290
341
|
@app.post("/assigning_value")
|
@@ -295,4 +346,64 @@ def assigning_value(request: Request):
|
|
295
346
|
)
|
296
347
|
updater.value = request.headers.get("my_custom_header")
|
297
348
|
updater.update_user_attribute_value()
|
349
|
+
|
350
|
+
@app.delete("/:user_attribute_name/:email")
|
351
|
+
def delete_user_attribute(user_attribute_name: str, email: str):
|
352
|
+
updater = UserAttributeUpdater(
|
353
|
+
user_attribute=user_attribute_name,
|
354
|
+
update_type="user",
|
355
|
+
email=email,
|
356
|
+
)
|
357
|
+
updater.delete_user_attribute_value()
|
358
|
+
|
359
|
+
## Optional Dependencies
|
360
|
+
|
361
|
+
The `lkr` CLI supports optional dependencies that enable additional functionality. You can install these individually or all at once.
|
362
|
+
|
363
|
+
### Available Extras
|
364
|
+
|
365
|
+
- **`mcp`**: Enables the MCP (Model Context Protocol) server functionality
|
366
|
+
- Includes: `mcp[cli]>=1.9.2`, `duckdb>=1.2.2`
|
367
|
+
- **`embed-observability`**: Enables the observability embed monitoring features
|
368
|
+
- Includes: `fastapi>=0.115.12`, `selenium>=4.32.0`
|
369
|
+
- **`user-attribute-updater`**: Enables the user attribute updater functionality
|
370
|
+
- Includes: `fastapi>=0.115.12`
|
371
|
+
|
372
|
+
### Installing Optional Dependencies
|
373
|
+
|
374
|
+
**Install all optional dependencies:**
|
375
|
+
```bash
|
376
|
+
uv sync --extra all
|
298
377
|
```
|
378
|
+
|
379
|
+
**Install specific extras:**
|
380
|
+
```bash
|
381
|
+
# Install MCP functionality
|
382
|
+
uv sync --extra mcp
|
383
|
+
|
384
|
+
# Install observability features
|
385
|
+
uv sync --extra embed-observability
|
386
|
+
|
387
|
+
# Install user attribute updater
|
388
|
+
uv sync --extra user-attribute-updater
|
389
|
+
|
390
|
+
# Install multiple extras
|
391
|
+
uv sync --extra mcp --extra embed-observability
|
392
|
+
```
|
393
|
+
|
394
|
+
**Using pip:**
|
395
|
+
```bash
|
396
|
+
# Install all optional dependencies
|
397
|
+
pip install lkr-dev-cli[all]
|
398
|
+
|
399
|
+
# Install specific extras
|
400
|
+
pip install lkr-dev-cli[mcp,embed-observability,user-attribute-updater]
|
401
|
+
```
|
402
|
+
|
403
|
+
### What Each Extra Enables
|
404
|
+
|
405
|
+
- **`mcp`**: Use the MCP server with tools like Cursor for enhanced IDE integration
|
406
|
+
- **`embed-observability`**: Run the observability embed server for monitoring Looker dashboard performance
|
407
|
+
- **`user-attribute-updater`**: Deploy the user attribute updater service for OIDC token management
|
408
|
+
|
409
|
+
All extras are designed to work together seamlessly, and installing `all` is equivalent to installing all individual extras.
|
@@ -1,25 +1,3 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: lkr-dev-cli
|
3
|
-
Version: 0.0.30
|
4
|
-
Summary: lkr: a command line interface for looker
|
5
|
-
Author: bwebs
|
6
|
-
License-Expression: MIT
|
7
|
-
License-File: LICENSE
|
8
|
-
Requires-Python: >=3.12
|
9
|
-
Requires-Dist: cryptography>=42.0.0
|
10
|
-
Requires-Dist: duckdb>=1.2.2
|
11
|
-
Requires-Dist: fastapi>=0.115.12
|
12
|
-
Requires-Dist: looker-sdk>=25.4.0
|
13
|
-
Requires-Dist: mcp[cli]>=1.9.2
|
14
|
-
Requires-Dist: pydantic>=2.11.4
|
15
|
-
Requires-Dist: pydash>=8.0.5
|
16
|
-
Requires-Dist: questionary>=2.1.0
|
17
|
-
Requires-Dist: requests>=2.31.0
|
18
|
-
Requires-Dist: selenium>=4.32.0
|
19
|
-
Requires-Dist: structlog>=25.3.0
|
20
|
-
Requires-Dist: typer>=0.15.2
|
21
|
-
Description-Content-Type: text/markdown
|
22
|
-
|
23
1
|
# lkr cli
|
24
2
|
|
25
3
|
The `lkr` cli is a tool for interacting with Looker. It combines Looker's SDK and customer logic to interact with Looker in meaninful ways. For a full list of commands, see the full [cli docs](./lkr.md)
|
@@ -214,10 +192,13 @@ This can also be used to stress test your Looker environment as it serves an API
|
|
214
192
|
## User Attribute Updater (OIDC Token)
|
215
193
|
|
216
194
|
1. Create a new cloud run using the `lkr-cli` public docker image `us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest`
|
217
|
-
2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings.
|
218
|
-
3.
|
219
|
-
|
220
|
-
|
195
|
+
2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings. See example [`gcloud` command](#example-gcloud-command)
|
196
|
+
3. For the command and arguments use:
|
197
|
+
- command: `lkr`
|
198
|
+
- args: `tools` `user-attribute-updater`
|
199
|
+
4. Deploy the cloud run
|
200
|
+
5. Retrieve the URL of the cloud run
|
201
|
+
6. Create the user attribute
|
221
202
|
- Name: cloud_run_access_token
|
222
203
|
- Data Type: String
|
223
204
|
- User Access: None
|
@@ -250,6 +231,23 @@ This can also be used to stress test your Looker environment as it serves an API
|
|
250
231
|
9. Check the logs of the cloud run to see if there was a 200 response
|
251
232
|
|
252
233
|
|
234
|
+
### Example `gcloud` command
|
235
|
+
```bash
|
236
|
+
export REGION=<your region>
|
237
|
+
export PROJECT=<your project id>
|
238
|
+
|
239
|
+
gcloud run deploy lkr-access-token-updater \
|
240
|
+
--image us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest \
|
241
|
+
--command lkr \
|
242
|
+
--args tools,user-attribute-updater \
|
243
|
+
--platform managed \
|
244
|
+
--region $REGION \
|
245
|
+
--project $PROJECT \
|
246
|
+
--cpu 1 \
|
247
|
+
--memory 2Gi \
|
248
|
+
--set-env-vars LOOKERSDK_CLIENT_ID=<your client id>,LOOKERSDK_CLIENT_SECRET=<your client secret>,LOOKERSDK_BASE_URL=<your instance url>,LOOKER_WHITELISTED_BASE_URLS=<your instance url>
|
249
|
+
```
|
250
|
+
|
253
251
|
## UserAttributeUpdater `lkr-dev-cli`
|
254
252
|
|
255
253
|
Exported from the `lkr-dev-cli` package is the `UserAttributeUpdater` pydantic class. This class has all the necessary logic to update a user attribute value.
|
@@ -301,12 +299,12 @@ from lkr import UserAttributeUpdater
|
|
301
299
|
def request_authorization(request: Request):
|
302
300
|
body = await request.json()
|
303
301
|
updater = UserAttributeUpdater.model_validate(body)
|
304
|
-
updater.get_request_authorization_for_value(request)
|
302
|
+
updater.get_request_authorization_for_value(request.headers.items())
|
305
303
|
updater.update_user_attribute_value()
|
306
304
|
|
307
305
|
@app.post("/as_body")
|
308
306
|
def as_body(request: Request, body: UserAttributeUpdater):
|
309
|
-
body.get_request_authorization_for_value(request)
|
307
|
+
body.get_request_authorization_for_value(request.headers.items())
|
310
308
|
body.update_user_attribute_value()
|
311
309
|
|
312
310
|
@app.post("/assigning_value")
|
@@ -317,4 +315,64 @@ def assigning_value(request: Request):
|
|
317
315
|
)
|
318
316
|
updater.value = request.headers.get("my_custom_header")
|
319
317
|
updater.update_user_attribute_value()
|
318
|
+
|
319
|
+
@app.delete("/:user_attribute_name/:email")
|
320
|
+
def delete_user_attribute(user_attribute_name: str, email: str):
|
321
|
+
updater = UserAttributeUpdater(
|
322
|
+
user_attribute=user_attribute_name,
|
323
|
+
update_type="user",
|
324
|
+
email=email,
|
325
|
+
)
|
326
|
+
updater.delete_user_attribute_value()
|
327
|
+
|
328
|
+
## Optional Dependencies
|
329
|
+
|
330
|
+
The `lkr` CLI supports optional dependencies that enable additional functionality. You can install these individually or all at once.
|
331
|
+
|
332
|
+
### Available Extras
|
333
|
+
|
334
|
+
- **`mcp`**: Enables the MCP (Model Context Protocol) server functionality
|
335
|
+
- Includes: `mcp[cli]>=1.9.2`, `duckdb>=1.2.2`
|
336
|
+
- **`embed-observability`**: Enables the observability embed monitoring features
|
337
|
+
- Includes: `fastapi>=0.115.12`, `selenium>=4.32.0`
|
338
|
+
- **`user-attribute-updater`**: Enables the user attribute updater functionality
|
339
|
+
- Includes: `fastapi>=0.115.12`
|
340
|
+
|
341
|
+
### Installing Optional Dependencies
|
342
|
+
|
343
|
+
**Install all optional dependencies:**
|
344
|
+
```bash
|
345
|
+
uv sync --extra all
|
320
346
|
```
|
347
|
+
|
348
|
+
**Install specific extras:**
|
349
|
+
```bash
|
350
|
+
# Install MCP functionality
|
351
|
+
uv sync --extra mcp
|
352
|
+
|
353
|
+
# Install observability features
|
354
|
+
uv sync --extra embed-observability
|
355
|
+
|
356
|
+
# Install user attribute updater
|
357
|
+
uv sync --extra user-attribute-updater
|
358
|
+
|
359
|
+
# Install multiple extras
|
360
|
+
uv sync --extra mcp --extra embed-observability
|
361
|
+
```
|
362
|
+
|
363
|
+
**Using pip:**
|
364
|
+
```bash
|
365
|
+
# Install all optional dependencies
|
366
|
+
pip install lkr-dev-cli[all]
|
367
|
+
|
368
|
+
# Install specific extras
|
369
|
+
pip install lkr-dev-cli[mcp,embed-observability,user-attribute-updater]
|
370
|
+
```
|
371
|
+
|
372
|
+
### What Each Extra Enables
|
373
|
+
|
374
|
+
- **`mcp`**: Use the MCP server with tools like Cursor for enhanced IDE integration
|
375
|
+
- **`embed-observability`**: Run the observability embed server for monitoring Looker dashboard performance
|
376
|
+
- **`user-attribute-updater`**: Deploy the user attribute updater service for OIDC token management
|
377
|
+
|
378
|
+
All extras are designed to work together seamlessly, and installing `all` is equivalent to installing all individual extras.
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from typing import Literal, Optional, Self, cast
|
2
2
|
|
3
|
-
from fastapi import Request
|
4
3
|
from looker_sdk.sdk.api40.methods import Looker40SDK
|
5
4
|
from looker_sdk.sdk.api40.models import (
|
6
5
|
UserAttributeGroupValue,
|
@@ -46,10 +45,12 @@ class UserAttributeUpdater(BaseModel):
|
|
46
45
|
)
|
47
46
|
return self
|
48
47
|
|
49
|
-
def get_request_authorization_for_value(self,
|
50
|
-
authorization_token =
|
48
|
+
def get_request_authorization_for_value(self, headers: list[tuple[str, str]]):
|
49
|
+
authorization_token = next(
|
50
|
+
(header for header in headers if header[0] == "Authorization"), None
|
51
|
+
)
|
51
52
|
if authorization_token:
|
52
|
-
self.value = authorization_token
|
53
|
+
self.value = authorization_token[1]
|
53
54
|
else:
|
54
55
|
logger.error("No authorization token found")
|
55
56
|
|
@@ -22,7 +22,7 @@ def user_attribute_updater(
|
|
22
22
|
@api.post("/identity_token")
|
23
23
|
def identity_token(request: Request, body: UserAttributeUpdater):
|
24
24
|
try:
|
25
|
-
body.get_request_authorization_for_value(request)
|
25
|
+
body.get_request_authorization_for_value(request.headers.items())
|
26
26
|
body.update_user_attribute_value()
|
27
27
|
raw_urls = os.getenv("LOOKER_WHITELISTED_BASE_URLS", "")
|
28
28
|
whitelisted_base_urls = (
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "lkr-dev-cli"
|
3
|
-
version = "0.0.
|
3
|
+
version = "0.0.31"
|
4
4
|
description = "lkr: a command line interface for looker"
|
5
5
|
readme = "README.md"
|
6
6
|
license = "MIT"
|
@@ -17,10 +17,25 @@ dependencies = [
|
|
17
17
|
"pydash>=8.0.5",
|
18
18
|
"structlog>=25.3.0",
|
19
19
|
"questionary>=2.1.0",
|
20
|
-
|
20
|
+
]
|
21
|
+
|
22
|
+
[project.optional-dependencies]
|
23
|
+
mcp = [
|
24
|
+
"mcp[cli]>=1.9.2",
|
25
|
+
"duckdb>=1.2.2"
|
26
|
+
]
|
27
|
+
embed-observability = [
|
21
28
|
"fastapi>=0.115.12",
|
22
|
-
"selenium>=4.32.0"
|
29
|
+
"selenium>=4.32.0"
|
30
|
+
]
|
31
|
+
user-attribute-updater = [
|
32
|
+
"fastapi>=0.115.12"
|
33
|
+
]
|
34
|
+
all = [
|
23
35
|
"mcp[cli]>=1.9.2",
|
36
|
+
"fastapi>=0.115.12",
|
37
|
+
"selenium>=4.32.0",
|
38
|
+
"duckdb>=1.2.2"
|
24
39
|
]
|
25
40
|
|
26
41
|
[project.scripts]
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Testing Dependency Resolution
|
2
|
+
|
3
|
+
This project includes tests to ensure that all dependency combinations resolve to the same lock file, maintaining consistency in the dependency tree.
|
4
|
+
|
5
|
+
## What the tests verify
|
6
|
+
|
7
|
+
The tests ensure that these two commands produce identical lock files:
|
8
|
+
|
9
|
+
1. `uv sync --extra all`
|
10
|
+
2. `uv sync --extra [all individual extras]`
|
11
|
+
|
12
|
+
Where "all individual extras" are dynamically discovered from `pyproject.toml` (excluding the `all` extra itself).
|
13
|
+
|
14
|
+
This is important because the `all` extra should be equivalent to installing all individual extras together.
|
15
|
+
|
16
|
+
## Running the tests
|
17
|
+
|
18
|
+
### Option 1: Shell script (recommended for quick testing)
|
19
|
+
|
20
|
+
```bash
|
21
|
+
./tests/test_deps.sh
|
22
|
+
```
|
23
|
+
|
24
|
+
This script will:
|
25
|
+
- Dynamically discover all individual extras from `pyproject.toml`
|
26
|
+
- Create temporary directories
|
27
|
+
- Run both dependency resolution commands
|
28
|
+
- Compare the resulting lock files
|
29
|
+
- Clean up automatically
|
30
|
+
|
31
|
+
### Option 2: Python test (for CI/CD integration)
|
32
|
+
|
33
|
+
```bash
|
34
|
+
# Run directly
|
35
|
+
python tests/test_dependency_resolution.py
|
36
|
+
|
37
|
+
# Run with pytest
|
38
|
+
uv run pytest tests/test_dependency_resolution.py -v
|
39
|
+
```
|
40
|
+
|
41
|
+
### Option 3: Makefile target
|
42
|
+
|
43
|
+
```bash
|
44
|
+
make test-deps
|
45
|
+
```
|
46
|
+
|
47
|
+
## What the tests check
|
48
|
+
|
49
|
+
1. **Dynamic Extra Discovery**: Automatically discovers all individual extras from `pyproject.toml`
|
50
|
+
2. **Dependency Resolution Consistency**: Ensures that `--extra all` and `--extra [individual extras]` resolve to the same set of packages
|
51
|
+
3. **Configuration Validation**: Verifies that all required extras are properly defined in `pyproject.toml`
|
52
|
+
4. **Lock File Integrity**: Compares SHA256 hashes of generated lock files
|
53
|
+
|
54
|
+
## Expected output
|
55
|
+
|
56
|
+
When the tests pass, you should see:
|
57
|
+
|
58
|
+
```
|
59
|
+
🔍 Discovering individual extras...
|
60
|
+
📦 Found individual extras: mcp embed-observability user-attribute-updater
|
61
|
+
🎉 SUCCESS: All dependency combinations resolve to the same lock file!
|
62
|
+
✅ Dependency resolution is consistent
|
63
|
+
```
|
64
|
+
|
65
|
+
## Adding new extras
|
66
|
+
|
67
|
+
When you add a new extra to `pyproject.toml`, the tests will automatically:
|
68
|
+
|
69
|
+
1. Discover the new extra
|
70
|
+
2. Include it in the dependency resolution test
|
71
|
+
3. Verify that `--extra all` still includes all dependencies from the new extra
|
72
|
+
|
73
|
+
No manual test updates are required!
|
74
|
+
|
75
|
+
## Troubleshooting
|
76
|
+
|
77
|
+
If the tests fail, it usually means:
|
78
|
+
|
79
|
+
1. **Missing dependencies**: The `all` extra doesn't include all the dependencies from individual extras
|
80
|
+
2. **Version conflicts**: Different dependency combinations resolve to different versions
|
81
|
+
3. **Configuration issues**: The `pyproject.toml` file has inconsistencies
|
82
|
+
|
83
|
+
### Common fixes
|
84
|
+
|
85
|
+
1. **Update the `all` extra**: Make sure it includes all dependencies from individual extras
|
86
|
+
2. **Check for version conflicts**: Ensure that all extras use compatible versions
|
87
|
+
3. **Verify dependency definitions**: Make sure all extras are properly defined
|
88
|
+
|
89
|
+
## CI/CD Integration
|
90
|
+
|
91
|
+
The tests are automatically run in GitHub Actions on:
|
92
|
+
- Push to `main` or `develop` branches
|
93
|
+
- Pull requests to `main` or `develop` branches
|
94
|
+
- Manual workflow dispatch
|
95
|
+
|
96
|
+
See `.github/workflows/test-dependencies.yml` for the CI configuration.
|