pvw-cli 1.0.9__tar.gz → 1.0.11__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.
Potentially problematic release.
This version of pvw-cli might be problematic. Click here for more details.
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/PKG-INFO +110 -22
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/README.md +107 -15
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/__init__.py +1 -1
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/entity.py +34 -0
- pvw_cli-1.0.11/purviewcli/cli/health.py +250 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/unified_catalog.py +519 -74
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/workflow.py +44 -4
- pvw_cli-1.0.11/purviewcli/client/_health.py +192 -0
- pvw_cli-1.0.11/purviewcli/client/_unified_catalog.py +935 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_workflow.py +3 -3
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/endpoint.py +21 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/sync_client.py +7 -2
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/PKG-INFO +110 -22
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/SOURCES.txt +2 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/requires.txt +2 -6
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pyproject.toml +3 -7
- pvw_cli-1.0.9/purviewcli/client/_unified_catalog.py +0 -315
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/__main__.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/__init__.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/account.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/cli.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/collections.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/domain.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/glossary.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/insight.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/lineage.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/management.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/policystore.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/relationship.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/scan.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/search.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/share.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/cli/types.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/__init__.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_account.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_collections.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_domain.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_entity.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_glossary.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_insight.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_lineage.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_management.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_policystore.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_relationship.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_scan.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_search.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_share.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/_types.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/api_client.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/business_rules.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/config.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/data_quality.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/endpoints.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/exceptions.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/lineage_visualization.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/monitoring_dashboard.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/rate_limiter.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/retry_handler.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/scanning_operations.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/client/settings.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/plugins/__init__.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/purviewcli/plugins/plugin_system.py +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/dependency_links.txt +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/entry_points.txt +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/not-zip-safe +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/pvw_cli.egg-info/top_level.txt +0 -0
- {pvw_cli-1.0.9 → pvw_cli-1.0.11}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pvw-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.11
|
|
4
4
|
Summary: Microsoft Purview CLI with comprehensive automation capabilities
|
|
5
5
|
Author-email: AYOUB KEBAILI <keayoub@msn.com>
|
|
6
6
|
Maintainer-email: AYOUB KEBAILI <keayoub@msn.com>
|
|
@@ -27,19 +27,15 @@ Classifier: Topic :: Database
|
|
|
27
27
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
28
28
|
Requires-Python: >=3.8
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
|
-
Requires-Dist: click>=8.0.0
|
|
31
|
-
Requires-Dist: rich>=12.0.0
|
|
32
30
|
Requires-Dist: azure-identity>=1.12.0
|
|
33
31
|
Requires-Dist: azure-core>=1.24.0
|
|
32
|
+
Requires-Dist: click>=8.0.0
|
|
33
|
+
Requires-Dist: rich>=12.0.0
|
|
34
34
|
Requires-Dist: requests>=2.28.0
|
|
35
35
|
Requires-Dist: pandas>=1.5.0
|
|
36
36
|
Requires-Dist: aiohttp>=3.8.0
|
|
37
37
|
Requires-Dist: pydantic<3.0.0,>=1.10.0
|
|
38
|
-
Requires-Dist: typer>=0.7.0
|
|
39
38
|
Requires-Dist: PyYAML>=6.0
|
|
40
|
-
Requires-Dist: python-dotenv>=0.19.0
|
|
41
|
-
Requires-Dist: asyncio-throttle>=1.0.0
|
|
42
|
-
Requires-Dist: tabulate>=0.9.0
|
|
43
39
|
Requires-Dist: cryptography<46.0.0,>=41.0.5
|
|
44
40
|
Provides-Extra: dev
|
|
45
41
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
@@ -60,21 +56,24 @@ Requires-Dist: pytest-asyncio>=0.20.0; extra == "test"
|
|
|
60
56
|
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
61
57
|
Requires-Dist: requests-mock>=1.9.0; extra == "test"
|
|
62
58
|
|
|
63
|
-
# PURVIEW CLI v1.0.
|
|
59
|
+
# PURVIEW CLI v1.0.11 - Microsoft Purview Automation & Data Governance
|
|
64
60
|
|
|
65
|
-
> **LATEST UPDATE (
|
|
61
|
+
> **LATEST UPDATE (October 2025):**
|
|
62
|
+
> - **🚀 NEW: Complete Data Product CRUD Operations** - Full update and delete support with smart partial updates
|
|
63
|
+
> - **🏥 NEW: Health Monitoring API** - Automated governance health checks and recommendations
|
|
64
|
+
> - **🔄 NEW: Workflow Management** - Approval workflows and business process automation
|
|
65
|
+
> - **✨ Enhanced ID Display** - Full UUIDs now visible in all list commands (no truncation)
|
|
66
66
|
> - **🚀 MAJOR: Complete Microsoft Purview Unified Catalog (UC) Support** (see new `uc` command group)
|
|
67
67
|
> - Full governance domains, glossary terms, data products, OKRs, and critical data elements management
|
|
68
68
|
> - Feature parity with UnifiedCatalogPy project with enhanced CLI experience
|
|
69
69
|
> - Advanced Data Product Management (legacy `data-product` command group)
|
|
70
70
|
> - Enhanced Discovery Query/Search support
|
|
71
|
-
> - **Fixed all command examples to use correct `pvw` command**
|
|
72
71
|
|
|
73
72
|
---
|
|
74
73
|
|
|
75
74
|
## What is PVW CLI?
|
|
76
75
|
|
|
77
|
-
**PVW CLI v1.0.
|
|
76
|
+
**PVW CLI v1.0.11** is a modern, full-featured command-line interface and Python library for Microsoft Purview. It enables automation and management of *all major Purview APIs* including:
|
|
78
77
|
|
|
79
78
|
- **NEW Unified Catalog (UC) Management** - Complete governance domains, glossary terms, data products, OKRs, CDEs (NEW)
|
|
80
79
|
- Entity management (create, update, bulk, import/export)
|
|
@@ -142,7 +141,7 @@ For more advanced usage, see the sections below or visit the [documentation](htt
|
|
|
142
141
|
|
|
143
142
|
## Overview
|
|
144
143
|
|
|
145
|
-
**PVW CLI v1.0.
|
|
144
|
+
**PVW CLI v1.0.11** is a modern command-line interface and Python library for Microsoft Purview, enabling:
|
|
146
145
|
|
|
147
146
|
- Advanced data catalog search and discovery
|
|
148
147
|
- Bulk import/export of entities, glossary terms, and lineage
|
|
@@ -553,23 +552,31 @@ pvw uc dataproduct create \
|
|
|
553
552
|
--name "Customer Analytics Dashboard" \
|
|
554
553
|
--domain-id "abc-123" \
|
|
555
554
|
--description "360-degree customer analytics with behavioral insights" \
|
|
556
|
-
--
|
|
555
|
+
--type Analytical \
|
|
556
|
+
--status Draft
|
|
557
557
|
|
|
558
558
|
# Get detailed data product information
|
|
559
|
-
pvw uc dataproduct
|
|
559
|
+
pvw uc dataproduct show --product-id "prod-789"
|
|
560
560
|
|
|
561
|
-
# Update data product
|
|
561
|
+
# Update data product (partial updates supported - only specify fields to change)
|
|
562
562
|
pvw uc dataproduct update \
|
|
563
563
|
--product-id "prod-789" \
|
|
564
|
-
--
|
|
565
|
-
--
|
|
566
|
-
--
|
|
564
|
+
--status Published \
|
|
565
|
+
--description "Updated comprehensive customer analytics" \
|
|
566
|
+
--endorsed
|
|
567
567
|
|
|
568
|
-
#
|
|
569
|
-
pvw uc dataproduct
|
|
568
|
+
# Update multiple fields at once
|
|
569
|
+
pvw uc dataproduct update \
|
|
570
570
|
--product-id "prod-789" \
|
|
571
|
-
--
|
|
572
|
-
--
|
|
571
|
+
--status Published \
|
|
572
|
+
--update-frequency Monthly \
|
|
573
|
+
--endorsed
|
|
574
|
+
|
|
575
|
+
# Delete a data product (with confirmation)
|
|
576
|
+
pvw uc dataproduct delete --product-id "prod-789"
|
|
577
|
+
|
|
578
|
+
# Delete without confirmation prompt
|
|
579
|
+
pvw uc dataproduct delete --product-id "prod-789" --yes
|
|
573
580
|
```
|
|
574
581
|
|
|
575
582
|
#### 🎯 **Objectives & Key Results (OKRs)**
|
|
@@ -614,6 +621,85 @@ pvw uc cde link \
|
|
|
614
621
|
--asset-id "ea3412c3-7387-4bc1-9923-11f6f6f60000"
|
|
615
622
|
```
|
|
616
623
|
|
|
624
|
+
#### 🏥 **Health Monitoring (NEW)**
|
|
625
|
+
|
|
626
|
+
Monitor governance health and get automated recommendations to improve your data governance posture.
|
|
627
|
+
|
|
628
|
+
```bash
|
|
629
|
+
# List all health findings and recommendations
|
|
630
|
+
pvw uc health query
|
|
631
|
+
|
|
632
|
+
# Filter by severity
|
|
633
|
+
pvw uc health query --severity High
|
|
634
|
+
pvw uc health query --severity Medium
|
|
635
|
+
|
|
636
|
+
# Filter by status
|
|
637
|
+
pvw uc health query --status NotStarted
|
|
638
|
+
pvw uc health query --status InProgress
|
|
639
|
+
|
|
640
|
+
# Get detailed information about a specific health action
|
|
641
|
+
pvw uc health show --action-id "5ea3fc78-6a77-4098-8779-ed81de6f87c9"
|
|
642
|
+
|
|
643
|
+
# Update health action status
|
|
644
|
+
pvw uc health update \
|
|
645
|
+
--action-id "5ea3fc78-6a77-4098-8779-ed81de6f87c9" \
|
|
646
|
+
--status InProgress \
|
|
647
|
+
--reason "Working on assigning glossary terms to data products"
|
|
648
|
+
|
|
649
|
+
# Get health summary statistics
|
|
650
|
+
pvw uc health summary
|
|
651
|
+
|
|
652
|
+
# Output health findings in JSON format
|
|
653
|
+
pvw uc health query --json
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
**Health Finding Types:**
|
|
657
|
+
- Missing glossary terms on data products (High)
|
|
658
|
+
- Data products without OKRs (Medium)
|
|
659
|
+
- Missing data quality scores (Medium)
|
|
660
|
+
- Classification gaps on data assets (Medium)
|
|
661
|
+
- Description quality issues (Medium)
|
|
662
|
+
- Business domains without critical data entities (Medium)
|
|
663
|
+
|
|
664
|
+
#### 🔄 **Workflow Management (NEW)**
|
|
665
|
+
|
|
666
|
+
Manage approval workflows and business process automation in Purview.
|
|
667
|
+
|
|
668
|
+
```bash
|
|
669
|
+
# List all workflows
|
|
670
|
+
pvw workflow list
|
|
671
|
+
|
|
672
|
+
# Get workflow details
|
|
673
|
+
pvw workflow get --workflow-id "workflow-123"
|
|
674
|
+
|
|
675
|
+
# Create a new workflow (requires JSON definition)
|
|
676
|
+
pvw workflow create --workflow-id "approval-flow-1" --payload-file workflow-definition.json
|
|
677
|
+
|
|
678
|
+
# Execute a workflow
|
|
679
|
+
pvw workflow execute --workflow-id "workflow-123"
|
|
680
|
+
|
|
681
|
+
# List workflow executions
|
|
682
|
+
pvw workflow executions --workflow-id "workflow-123"
|
|
683
|
+
|
|
684
|
+
# View specific execution details
|
|
685
|
+
pvw workflow execution-details --workflow-id "workflow-123" --execution-id "exec-456"
|
|
686
|
+
|
|
687
|
+
# Update workflow configuration
|
|
688
|
+
pvw workflow update --workflow-id "workflow-123" --payload-file updated-workflow.json
|
|
689
|
+
|
|
690
|
+
# Delete a workflow
|
|
691
|
+
pvw workflow delete --workflow-id "workflow-123"
|
|
692
|
+
|
|
693
|
+
# Output workflows in JSON format
|
|
694
|
+
pvw workflow list --json
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Workflow Use Cases:**
|
|
698
|
+
- Data access request approvals
|
|
699
|
+
- Glossary term certification workflows
|
|
700
|
+
- Data product publishing approvals
|
|
701
|
+
- Classification review processes
|
|
702
|
+
|
|
617
703
|
#### 🔄 **Integrated Workflow Example**
|
|
618
704
|
|
|
619
705
|
```bash
|
|
@@ -765,6 +851,8 @@ PVW CLI provides comprehensive automation for all major Microsoft Purview APIs,
|
|
|
765
851
|
### Supported API Groups
|
|
766
852
|
|
|
767
853
|
- **Unified Catalog**: Complete governance domains, glossary terms, data products, OKRs, CDEs management ✅
|
|
854
|
+
- **Health Monitoring**: Automated governance health checks and recommendations ✅ NEW
|
|
855
|
+
- **Workflows**: Approval workflows and business process automation ✅ NEW
|
|
768
856
|
- **Data Map**: Full entity and lineage management ✅
|
|
769
857
|
- **Discovery**: Advanced search, browse, and query capabilities ✅
|
|
770
858
|
- **Collections**: Collection and account management ✅
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
# PURVIEW CLI v1.0.
|
|
1
|
+
# PURVIEW CLI v1.0.11 - Microsoft Purview Automation & Data Governance
|
|
2
2
|
|
|
3
|
-
> **LATEST UPDATE (
|
|
3
|
+
> **LATEST UPDATE (October 2025):**
|
|
4
|
+
> - **🚀 NEW: Complete Data Product CRUD Operations** - Full update and delete support with smart partial updates
|
|
5
|
+
> - **🏥 NEW: Health Monitoring API** - Automated governance health checks and recommendations
|
|
6
|
+
> - **🔄 NEW: Workflow Management** - Approval workflows and business process automation
|
|
7
|
+
> - **✨ Enhanced ID Display** - Full UUIDs now visible in all list commands (no truncation)
|
|
4
8
|
> - **🚀 MAJOR: Complete Microsoft Purview Unified Catalog (UC) Support** (see new `uc` command group)
|
|
5
9
|
> - Full governance domains, glossary terms, data products, OKRs, and critical data elements management
|
|
6
10
|
> - Feature parity with UnifiedCatalogPy project with enhanced CLI experience
|
|
7
11
|
> - Advanced Data Product Management (legacy `data-product` command group)
|
|
8
12
|
> - Enhanced Discovery Query/Search support
|
|
9
|
-
> - **Fixed all command examples to use correct `pvw` command**
|
|
10
13
|
|
|
11
14
|
---
|
|
12
15
|
|
|
13
16
|
## What is PVW CLI?
|
|
14
17
|
|
|
15
|
-
**PVW CLI v1.0.
|
|
18
|
+
**PVW CLI v1.0.11** is a modern, full-featured command-line interface and Python library for Microsoft Purview. It enables automation and management of *all major Purview APIs* including:
|
|
16
19
|
|
|
17
20
|
- **NEW Unified Catalog (UC) Management** - Complete governance domains, glossary terms, data products, OKRs, CDEs (NEW)
|
|
18
21
|
- Entity management (create, update, bulk, import/export)
|
|
@@ -80,7 +83,7 @@ For more advanced usage, see the sections below or visit the [documentation](htt
|
|
|
80
83
|
|
|
81
84
|
## Overview
|
|
82
85
|
|
|
83
|
-
**PVW CLI v1.0.
|
|
86
|
+
**PVW CLI v1.0.11** is a modern command-line interface and Python library for Microsoft Purview, enabling:
|
|
84
87
|
|
|
85
88
|
- Advanced data catalog search and discovery
|
|
86
89
|
- Bulk import/export of entities, glossary terms, and lineage
|
|
@@ -491,23 +494,31 @@ pvw uc dataproduct create \
|
|
|
491
494
|
--name "Customer Analytics Dashboard" \
|
|
492
495
|
--domain-id "abc-123" \
|
|
493
496
|
--description "360-degree customer analytics with behavioral insights" \
|
|
494
|
-
--
|
|
497
|
+
--type Analytical \
|
|
498
|
+
--status Draft
|
|
495
499
|
|
|
496
500
|
# Get detailed data product information
|
|
497
|
-
pvw uc dataproduct
|
|
501
|
+
pvw uc dataproduct show --product-id "prod-789"
|
|
498
502
|
|
|
499
|
-
# Update data product
|
|
503
|
+
# Update data product (partial updates supported - only specify fields to change)
|
|
500
504
|
pvw uc dataproduct update \
|
|
501
505
|
--product-id "prod-789" \
|
|
502
|
-
--
|
|
503
|
-
--
|
|
504
|
-
--
|
|
506
|
+
--status Published \
|
|
507
|
+
--description "Updated comprehensive customer analytics" \
|
|
508
|
+
--endorsed
|
|
505
509
|
|
|
506
|
-
#
|
|
507
|
-
pvw uc dataproduct
|
|
510
|
+
# Update multiple fields at once
|
|
511
|
+
pvw uc dataproduct update \
|
|
508
512
|
--product-id "prod-789" \
|
|
509
|
-
--
|
|
510
|
-
--
|
|
513
|
+
--status Published \
|
|
514
|
+
--update-frequency Monthly \
|
|
515
|
+
--endorsed
|
|
516
|
+
|
|
517
|
+
# Delete a data product (with confirmation)
|
|
518
|
+
pvw uc dataproduct delete --product-id "prod-789"
|
|
519
|
+
|
|
520
|
+
# Delete without confirmation prompt
|
|
521
|
+
pvw uc dataproduct delete --product-id "prod-789" --yes
|
|
511
522
|
```
|
|
512
523
|
|
|
513
524
|
#### 🎯 **Objectives & Key Results (OKRs)**
|
|
@@ -552,6 +563,85 @@ pvw uc cde link \
|
|
|
552
563
|
--asset-id "ea3412c3-7387-4bc1-9923-11f6f6f60000"
|
|
553
564
|
```
|
|
554
565
|
|
|
566
|
+
#### 🏥 **Health Monitoring (NEW)**
|
|
567
|
+
|
|
568
|
+
Monitor governance health and get automated recommendations to improve your data governance posture.
|
|
569
|
+
|
|
570
|
+
```bash
|
|
571
|
+
# List all health findings and recommendations
|
|
572
|
+
pvw uc health query
|
|
573
|
+
|
|
574
|
+
# Filter by severity
|
|
575
|
+
pvw uc health query --severity High
|
|
576
|
+
pvw uc health query --severity Medium
|
|
577
|
+
|
|
578
|
+
# Filter by status
|
|
579
|
+
pvw uc health query --status NotStarted
|
|
580
|
+
pvw uc health query --status InProgress
|
|
581
|
+
|
|
582
|
+
# Get detailed information about a specific health action
|
|
583
|
+
pvw uc health show --action-id "5ea3fc78-6a77-4098-8779-ed81de6f87c9"
|
|
584
|
+
|
|
585
|
+
# Update health action status
|
|
586
|
+
pvw uc health update \
|
|
587
|
+
--action-id "5ea3fc78-6a77-4098-8779-ed81de6f87c9" \
|
|
588
|
+
--status InProgress \
|
|
589
|
+
--reason "Working on assigning glossary terms to data products"
|
|
590
|
+
|
|
591
|
+
# Get health summary statistics
|
|
592
|
+
pvw uc health summary
|
|
593
|
+
|
|
594
|
+
# Output health findings in JSON format
|
|
595
|
+
pvw uc health query --json
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
**Health Finding Types:**
|
|
599
|
+
- Missing glossary terms on data products (High)
|
|
600
|
+
- Data products without OKRs (Medium)
|
|
601
|
+
- Missing data quality scores (Medium)
|
|
602
|
+
- Classification gaps on data assets (Medium)
|
|
603
|
+
- Description quality issues (Medium)
|
|
604
|
+
- Business domains without critical data entities (Medium)
|
|
605
|
+
|
|
606
|
+
#### 🔄 **Workflow Management (NEW)**
|
|
607
|
+
|
|
608
|
+
Manage approval workflows and business process automation in Purview.
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
# List all workflows
|
|
612
|
+
pvw workflow list
|
|
613
|
+
|
|
614
|
+
# Get workflow details
|
|
615
|
+
pvw workflow get --workflow-id "workflow-123"
|
|
616
|
+
|
|
617
|
+
# Create a new workflow (requires JSON definition)
|
|
618
|
+
pvw workflow create --workflow-id "approval-flow-1" --payload-file workflow-definition.json
|
|
619
|
+
|
|
620
|
+
# Execute a workflow
|
|
621
|
+
pvw workflow execute --workflow-id "workflow-123"
|
|
622
|
+
|
|
623
|
+
# List workflow executions
|
|
624
|
+
pvw workflow executions --workflow-id "workflow-123"
|
|
625
|
+
|
|
626
|
+
# View specific execution details
|
|
627
|
+
pvw workflow execution-details --workflow-id "workflow-123" --execution-id "exec-456"
|
|
628
|
+
|
|
629
|
+
# Update workflow configuration
|
|
630
|
+
pvw workflow update --workflow-id "workflow-123" --payload-file updated-workflow.json
|
|
631
|
+
|
|
632
|
+
# Delete a workflow
|
|
633
|
+
pvw workflow delete --workflow-id "workflow-123"
|
|
634
|
+
|
|
635
|
+
# Output workflows in JSON format
|
|
636
|
+
pvw workflow list --json
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
**Workflow Use Cases:**
|
|
640
|
+
- Data access request approvals
|
|
641
|
+
- Glossary term certification workflows
|
|
642
|
+
- Data product publishing approvals
|
|
643
|
+
- Classification review processes
|
|
644
|
+
|
|
555
645
|
#### 🔄 **Integrated Workflow Example**
|
|
556
646
|
|
|
557
647
|
```bash
|
|
@@ -703,6 +793,8 @@ PVW CLI provides comprehensive automation for all major Microsoft Purview APIs,
|
|
|
703
793
|
### Supported API Groups
|
|
704
794
|
|
|
705
795
|
- **Unified Catalog**: Complete governance domains, glossary terms, data products, OKRs, CDEs management ✅
|
|
796
|
+
- **Health Monitoring**: Automated governance health checks and recommendations ✅ NEW
|
|
797
|
+
- **Workflows**: Approval workflows and business process automation ✅ NEW
|
|
706
798
|
- **Data Map**: Full entity and lineage management ✅
|
|
707
799
|
- **Discovery**: Advanced search, browse, and query capabilities ✅
|
|
708
800
|
- **Collections**: Collection and account management ✅
|
|
@@ -168,6 +168,40 @@ def bulk_create(ctx, payload_file):
|
|
|
168
168
|
console.print(f"[red]✗ Error executing entity bulk-create: {str(e)}[/red]")
|
|
169
169
|
|
|
170
170
|
|
|
171
|
+
@entity.command(name="bulk-update")
|
|
172
|
+
@click.option(
|
|
173
|
+
"--payload-file",
|
|
174
|
+
required=True,
|
|
175
|
+
type=click.Path(exists=True),
|
|
176
|
+
help="File path to a valid JSON document containing entities to update/create (same shape as bulk-create).",
|
|
177
|
+
)
|
|
178
|
+
@click.pass_context
|
|
179
|
+
def bulk_update(ctx, payload_file):
|
|
180
|
+
"""Bulk update/create entities from a JSON payload file (uses qualifiedName to match existing entities)."""
|
|
181
|
+
try:
|
|
182
|
+
if ctx.obj.get("mock"):
|
|
183
|
+
console.print("[yellow]🎭 Mock: entity bulk-update command[/yellow]")
|
|
184
|
+
console.print(f"[dim]Payload File: {payload_file}[/dim]")
|
|
185
|
+
console.print("[green]✓ Mock entity bulk-update completed successfully[/green]")
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
args = {"--payloadFile": payload_file}
|
|
189
|
+
|
|
190
|
+
from purviewcli.client._entity import Entity
|
|
191
|
+
|
|
192
|
+
entity_client = Entity()
|
|
193
|
+
result = entity_client.entityBulkCreateOrUpdate(args)
|
|
194
|
+
|
|
195
|
+
if result:
|
|
196
|
+
console.print("[green]✓ Entity bulk-update completed successfully[/green]")
|
|
197
|
+
console.print(json.dumps(result, indent=2))
|
|
198
|
+
else:
|
|
199
|
+
console.print("[yellow]⚠ Entity bulk-update completed with no result[/yellow]")
|
|
200
|
+
|
|
201
|
+
except Exception as e:
|
|
202
|
+
console.print(f"[red]✗ Error executing entity bulk-update: {str(e)}[/red]")
|
|
203
|
+
|
|
204
|
+
|
|
171
205
|
# === BULK OPERATIONS ===
|
|
172
206
|
|
|
173
207
|
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Health CLI commands for Microsoft Purview Unified Catalog
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from purviewcli.client._health import Health
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.group()
|
|
15
|
+
def health():
|
|
16
|
+
"""Health monitoring and governance recommendations."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@health.command()
|
|
21
|
+
@click.option("--domain-id", help="Filter by governance domain ID")
|
|
22
|
+
@click.option("--severity", help="Filter by severity: High, Medium, Low")
|
|
23
|
+
@click.option("--status", help="Filter by status: NotStarted, InProgress, Resolved, Dismissed")
|
|
24
|
+
@click.option("--finding-type", help="Filter by finding type (e.g., 'Estate Curation')")
|
|
25
|
+
@click.option("--target-entity-type", help="Filter by target entity type (e.g., DataProduct, Term)")
|
|
26
|
+
def query(domain_id, severity, status, finding_type, target_entity_type):
|
|
27
|
+
"""Query health actions (findings and recommendations)."""
|
|
28
|
+
client = Health()
|
|
29
|
+
|
|
30
|
+
args = {
|
|
31
|
+
"--domain-id": [domain_id] if domain_id else [""],
|
|
32
|
+
"--severity": [severity] if severity else [""],
|
|
33
|
+
"--status": [status] if status else [""],
|
|
34
|
+
"--finding-type": [finding_type] if finding_type else [""],
|
|
35
|
+
"--target-entity-type": [target_entity_type] if target_entity_type else [""]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
result = client.query_health_actions(args)
|
|
39
|
+
|
|
40
|
+
# get_data() in endpoint.py returns just the data part
|
|
41
|
+
if result and isinstance(result, dict):
|
|
42
|
+
actions = result.get("value", [])
|
|
43
|
+
|
|
44
|
+
if not actions:
|
|
45
|
+
console.print("[yellow]No health actions found matching the filters.[/yellow]")
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
# Create summary table
|
|
49
|
+
table = Table(title=f"Health Actions ({len(actions)} found)", show_lines=True)
|
|
50
|
+
table.add_column("ID", style="cyan", no_wrap=False)
|
|
51
|
+
table.add_column("Finding", style="white", no_wrap=False)
|
|
52
|
+
table.add_column("Severity", style="yellow")
|
|
53
|
+
table.add_column("Status", style="green")
|
|
54
|
+
table.add_column("Target", style="magenta", no_wrap=False)
|
|
55
|
+
table.add_column("Domain", style="blue", no_wrap=False)
|
|
56
|
+
|
|
57
|
+
for action in actions:
|
|
58
|
+
# Color severity
|
|
59
|
+
severity_text = action.get("severity", "N/A")
|
|
60
|
+
if severity_text == "High":
|
|
61
|
+
severity_style = "[red]High[/red]"
|
|
62
|
+
elif severity_text == "Medium":
|
|
63
|
+
severity_style = "[yellow]Medium[/yellow]"
|
|
64
|
+
else:
|
|
65
|
+
severity_style = "[green]Low[/green]"
|
|
66
|
+
|
|
67
|
+
# Color status
|
|
68
|
+
status_text = action.get("status", "N/A")
|
|
69
|
+
if status_text == "NotStarted":
|
|
70
|
+
status_style = "[red]Not Started[/red]"
|
|
71
|
+
elif status_text == "InProgress":
|
|
72
|
+
status_style = "[yellow]In Progress[/yellow]"
|
|
73
|
+
elif status_text == "Resolved":
|
|
74
|
+
status_style = "[green]Resolved[/green]"
|
|
75
|
+
else:
|
|
76
|
+
status_style = status_text
|
|
77
|
+
|
|
78
|
+
# Truncate IDs for display
|
|
79
|
+
action_id = action.get("id", "N/A")
|
|
80
|
+
short_id = action_id[:13] + "..." if len(action_id) > 16 else action_id
|
|
81
|
+
|
|
82
|
+
domain_id_val = action.get("domainId", "N/A")
|
|
83
|
+
short_domain = domain_id_val[:13] + "..." if len(domain_id_val) > 16 else domain_id_val
|
|
84
|
+
|
|
85
|
+
table.add_row(
|
|
86
|
+
short_id,
|
|
87
|
+
action.get("findingName", "N/A"),
|
|
88
|
+
severity_style,
|
|
89
|
+
status_style,
|
|
90
|
+
action.get("targetEntityType", "N/A"),
|
|
91
|
+
short_domain
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
console.print(table)
|
|
95
|
+
console.print(f"\n[dim]Showing {len(actions)} health action(s)[/dim]")
|
|
96
|
+
console.print("[dim]Use 'pvcli uc health show --action-id <id>' for details[/dim]")
|
|
97
|
+
else:
|
|
98
|
+
console.print("[red]Failed to retrieve health actions.[/red]")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@health.command()
|
|
102
|
+
@click.option("--action-id", required=True, help="Health action ID")
|
|
103
|
+
def show(action_id):
|
|
104
|
+
"""Show detailed information about a health action."""
|
|
105
|
+
client = Health()
|
|
106
|
+
args = {"--action-id": [action_id]}
|
|
107
|
+
|
|
108
|
+
result = client.get_health_action(args)
|
|
109
|
+
|
|
110
|
+
# get_data() returns just the data part
|
|
111
|
+
if result and isinstance(result, dict) and "id" in result:
|
|
112
|
+
action = result
|
|
113
|
+
|
|
114
|
+
console.print(f"\n[bold cyan]Health Action Details[/bold cyan]\n")
|
|
115
|
+
|
|
116
|
+
# Basic info
|
|
117
|
+
console.print(f"[bold]ID:[/bold] {action.get('id', 'N/A')}")
|
|
118
|
+
console.print(f"[bold]Finding ID:[/bold] {action.get('findingId', 'N/A')}")
|
|
119
|
+
console.print(f"[bold]Name:[/bold] {action.get('findingName', 'N/A')}")
|
|
120
|
+
|
|
121
|
+
# Severity with color
|
|
122
|
+
severity = action.get("severity", "N/A")
|
|
123
|
+
severity_color = "red" if severity == "High" else "yellow" if severity == "Medium" else "green"
|
|
124
|
+
console.print(f"[bold]Severity:[/bold] [{severity_color}]{severity}[/{severity_color}]")
|
|
125
|
+
|
|
126
|
+
# Status with color
|
|
127
|
+
status = action.get("status", "N/A")
|
|
128
|
+
status_color = "red" if status == "NotStarted" else "yellow" if status == "InProgress" else "green"
|
|
129
|
+
console.print(f"[bold]Status:[/bold] [{status_color}]{status}[/{status_color}]")
|
|
130
|
+
|
|
131
|
+
# Category and types
|
|
132
|
+
console.print(f"\n[bold]Category:[/bold] {action.get('category', 'N/A')}")
|
|
133
|
+
console.print(f"[bold]Finding Type:[/bold] {action.get('findingType', 'N/A')}")
|
|
134
|
+
console.print(f"[bold]Finding SubType:[/bold] {action.get('findingSubType', 'N/A')}")
|
|
135
|
+
|
|
136
|
+
# Target
|
|
137
|
+
console.print(f"\n[bold]Target Entity Type:[/bold] {action.get('targetEntityType', 'N/A')}")
|
|
138
|
+
console.print(f"[bold]Target Entity ID:[/bold] {action.get('targetEntityId', 'N/A')}")
|
|
139
|
+
console.print(f"[bold]Domain ID:[/bold] {action.get('domainId', 'N/A')}")
|
|
140
|
+
|
|
141
|
+
# Recommendation
|
|
142
|
+
recommendation = action.get("recommendation", "")
|
|
143
|
+
if recommendation:
|
|
144
|
+
console.print(f"\n[bold]Recommendation:[/bold]\n{recommendation}")
|
|
145
|
+
|
|
146
|
+
# Reason
|
|
147
|
+
reason = action.get("reason", "")
|
|
148
|
+
if reason:
|
|
149
|
+
console.print(f"\n[bold]Reason:[/bold]\n{reason}")
|
|
150
|
+
|
|
151
|
+
# Assignment
|
|
152
|
+
assigned_to = action.get("assignedTo", [])
|
|
153
|
+
if assigned_to:
|
|
154
|
+
console.print(f"\n[bold]Assigned To:[/bold]")
|
|
155
|
+
for user_id in assigned_to:
|
|
156
|
+
console.print(f" • {user_id}")
|
|
157
|
+
else:
|
|
158
|
+
console.print(f"\n[bold]Assigned To:[/bold] [yellow]Not assigned[/yellow]")
|
|
159
|
+
|
|
160
|
+
# System data
|
|
161
|
+
system_data = action.get("systemData", {})
|
|
162
|
+
if system_data:
|
|
163
|
+
console.print(f"\n[bold]System Information:[/bold]")
|
|
164
|
+
console.print(f" Created At: {system_data.get('createdAt', 'N/A')}")
|
|
165
|
+
console.print(f" Created By: {system_data.get('createdBy', 'N/A')}")
|
|
166
|
+
console.print(f" Last Modified: {system_data.get('lastModifiedAt', 'N/A')}")
|
|
167
|
+
console.print(f" Last Modified By: {system_data.get('lastModifiedBy', 'N/A')}")
|
|
168
|
+
console.print(f" Last Hint At: {system_data.get('lastHintAt', 'N/A')}")
|
|
169
|
+
|
|
170
|
+
console.print()
|
|
171
|
+
else:
|
|
172
|
+
console.print(f"[red]Failed to retrieve health action: {action_id}[/red]")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@health.command()
|
|
176
|
+
@click.option("--action-id", required=True, help="Health action ID")
|
|
177
|
+
@click.option("--status", help="New status: NotStarted, InProgress, Resolved, Dismissed")
|
|
178
|
+
@click.option("--assigned-to", help="User ID or email to assign to")
|
|
179
|
+
@click.option("--reason", help="Reason for the update")
|
|
180
|
+
def update(action_id, status, assigned_to, reason):
|
|
181
|
+
"""Update a health action (status, assignment, etc.)."""
|
|
182
|
+
if not status and not assigned_to and not reason:
|
|
183
|
+
console.print("[red]Error: At least one of --status, --assigned-to, or --reason must be provided.[/red]")
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
client = Health()
|
|
187
|
+
args = {
|
|
188
|
+
"--action-id": [action_id],
|
|
189
|
+
"--status": [status] if status else [""],
|
|
190
|
+
"--assigned-to": [assigned_to] if assigned_to else [""],
|
|
191
|
+
"--reason": [reason] if reason else [""]
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
result = client.update_health_action(args)
|
|
195
|
+
|
|
196
|
+
if result and result.get("status") == "success":
|
|
197
|
+
console.print(f"[green]✓[/green] Health action updated successfully: {action_id}")
|
|
198
|
+
if status:
|
|
199
|
+
console.print(f" Status: {status}")
|
|
200
|
+
if assigned_to:
|
|
201
|
+
console.print(f" Assigned to: {assigned_to}")
|
|
202
|
+
if reason:
|
|
203
|
+
console.print(f" Reason: {reason}")
|
|
204
|
+
else:
|
|
205
|
+
console.print(f"[red]Failed to update health action: {action_id}[/red]")
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@health.command()
|
|
209
|
+
@click.option("--action-id", required=True, help="Health action ID")
|
|
210
|
+
@click.confirmation_option(prompt="Are you sure you want to delete this health action?")
|
|
211
|
+
def delete(action_id):
|
|
212
|
+
"""Delete a health action."""
|
|
213
|
+
client = Health()
|
|
214
|
+
args = {"--action-id": [action_id]}
|
|
215
|
+
|
|
216
|
+
result = client.delete_health_action(args)
|
|
217
|
+
|
|
218
|
+
if result and result.get("status") == "success":
|
|
219
|
+
console.print(f"[green]✓[/green] Health action deleted successfully: {action_id}")
|
|
220
|
+
else:
|
|
221
|
+
console.print(f"[red]Failed to delete health action: {action_id}[/red]")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@health.command()
|
|
225
|
+
@click.option("--domain-id", help="Get summary for specific domain")
|
|
226
|
+
def summary(domain_id):
|
|
227
|
+
"""Get health summary statistics."""
|
|
228
|
+
client = Health()
|
|
229
|
+
args = {"--domain-id": [domain_id] if domain_id else [""]}
|
|
230
|
+
|
|
231
|
+
result = client.get_health_summary(args)
|
|
232
|
+
|
|
233
|
+
if result and result.get("data"):
|
|
234
|
+
summary_data = result["data"]
|
|
235
|
+
|
|
236
|
+
console.print("\n[bold cyan]Health Summary[/bold cyan]\n")
|
|
237
|
+
|
|
238
|
+
# Display summary statistics
|
|
239
|
+
console.print(f"Total Actions: {summary_data.get('total', 'N/A')}")
|
|
240
|
+
console.print(f"High Severity: [red]{summary_data.get('high', 'N/A')}[/red]")
|
|
241
|
+
console.print(f"Medium Severity: [yellow]{summary_data.get('medium', 'N/A')}[/yellow]")
|
|
242
|
+
console.print(f"Low Severity: [green]{summary_data.get('low', 'N/A')}[/green]")
|
|
243
|
+
console.print(f"\nNot Started: [red]{summary_data.get('notStarted', 'N/A')}[/red]")
|
|
244
|
+
console.print(f"In Progress: [yellow]{summary_data.get('inProgress', 'N/A')}[/yellow]")
|
|
245
|
+
console.print(f"Resolved: [green]{summary_data.get('resolved', 'N/A')}[/green]")
|
|
246
|
+
|
|
247
|
+
console.print()
|
|
248
|
+
else:
|
|
249
|
+
console.print("[yellow]Summary endpoint may not be available or no data returned.[/yellow]")
|
|
250
|
+
console.print("[dim]Try using 'pvcli uc health query' to see all actions.[/dim]")
|