pvw-cli 1.0.8__py3-none-any.whl → 1.0.10__py3-none-any.whl
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.
- purviewcli/__init__.py +1 -1
- purviewcli/cli/health.py +250 -0
- purviewcli/cli/search.py +201 -10
- purviewcli/cli/unified_catalog.py +678 -142
- purviewcli/cli/workflow.py +44 -4
- purviewcli/client/_health.py +192 -0
- purviewcli/client/_unified_catalog.py +728 -62
- purviewcli/client/_workflow.py +3 -3
- purviewcli/client/endpoint.py +21 -0
- purviewcli/client/sync_client.py +13 -8
- pvw_cli-1.0.10.dist-info/METADATA +888 -0
- {pvw_cli-1.0.8.dist-info → pvw_cli-1.0.10.dist-info}/RECORD +15 -13
- pvw_cli-1.0.8.dist-info/METADATA +0 -458
- {pvw_cli-1.0.8.dist-info → pvw_cli-1.0.10.dist-info}/WHEEL +0 -0
- {pvw_cli-1.0.8.dist-info → pvw_cli-1.0.10.dist-info}/entry_points.txt +0 -0
- {pvw_cli-1.0.8.dist-info → pvw_cli-1.0.10.dist-info}/top_level.txt +0 -0
purviewcli/cli/workflow.py
CHANGED
|
@@ -20,8 +20,9 @@ def workflow():
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@workflow.command()
|
|
23
|
+
@click.option("--json", "output_json", is_flag=True, help="Output results in JSON format")
|
|
23
24
|
@click.pass_context
|
|
24
|
-
def list(ctx):
|
|
25
|
+
def list(ctx, output_json):
|
|
25
26
|
"""List all workflows."""
|
|
26
27
|
try:
|
|
27
28
|
if ctx.obj and ctx.obj.get("mock"):
|
|
@@ -30,16 +31,55 @@ def list(ctx):
|
|
|
30
31
|
return
|
|
31
32
|
|
|
32
33
|
from purviewcli.client._workflow import Workflow
|
|
34
|
+
from rich.table import Table
|
|
33
35
|
|
|
34
36
|
args = {}
|
|
35
37
|
workflow_client = Workflow()
|
|
36
38
|
result = workflow_client.workflowListWorkflows(args)
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
# Handle response structure
|
|
41
|
+
if isinstance(result, dict):
|
|
42
|
+
workflows = result.get("results", []) or result.get("value", [])
|
|
43
|
+
elif isinstance(result, (list, tuple)):
|
|
44
|
+
workflows = result
|
|
41
45
|
else:
|
|
46
|
+
workflows = []
|
|
47
|
+
|
|
48
|
+
if not workflows:
|
|
42
49
|
console.print("[yellow]⚠ No workflows found[/yellow]")
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
# Output in JSON format if requested
|
|
53
|
+
if output_json:
|
|
54
|
+
console.print(json.dumps(workflows, indent=2))
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
table = Table(title="Workflows", show_lines=True)
|
|
58
|
+
table.add_column("ID", style="cyan", no_wrap=True, width=38)
|
|
59
|
+
table.add_column("Name", style="green", width=30)
|
|
60
|
+
table.add_column("Type", style="blue")
|
|
61
|
+
table.add_column("Status", style="yellow")
|
|
62
|
+
table.add_column("Description", style="white")
|
|
63
|
+
|
|
64
|
+
for wf in workflows:
|
|
65
|
+
if not isinstance(wf, dict):
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
workflow_id = wf.get("id", "N/A")
|
|
69
|
+
name = wf.get("name", "N/A")
|
|
70
|
+
wf_type = wf.get("type", "N/A")
|
|
71
|
+
status = wf.get("status", "N/A")
|
|
72
|
+
description = wf.get("description", "")
|
|
73
|
+
|
|
74
|
+
# Truncate description if too long
|
|
75
|
+
if len(description) > 60:
|
|
76
|
+
description = description[:60] + "..."
|
|
77
|
+
|
|
78
|
+
table.add_row(workflow_id, name, wf_type, status, description)
|
|
79
|
+
|
|
80
|
+
console.print(table)
|
|
81
|
+
console.print(f"\n[dim]Total: {len(workflows)} workflow(s)[/dim]")
|
|
82
|
+
|
|
43
83
|
except Exception as e:
|
|
44
84
|
console.print(f"[red]✗ Error executing workflow list: {str(e)}[/red]")
|
|
45
85
|
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Health API Client for Microsoft Purview Unified Catalog
|
|
3
|
+
Provides governance health monitoring and recommendations
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .endpoint import Endpoint, decorator, no_api_call_decorator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Health(Endpoint):
|
|
10
|
+
"""Health API operations for governance monitoring.
|
|
11
|
+
|
|
12
|
+
API Version: 2024-02-01-preview
|
|
13
|
+
Base Path: /datagovernance/health
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
Endpoint.__init__(self)
|
|
18
|
+
self.app = "datagovernance"
|
|
19
|
+
|
|
20
|
+
# ========================================
|
|
21
|
+
# HEALTH ACTIONS
|
|
22
|
+
# ========================================
|
|
23
|
+
|
|
24
|
+
@decorator
|
|
25
|
+
def query_health_actions(self, args):
|
|
26
|
+
"""Query health actions (findings and recommendations).
|
|
27
|
+
|
|
28
|
+
Returns governance health findings including:
|
|
29
|
+
- Missing metadata
|
|
30
|
+
- Incomplete governance
|
|
31
|
+
- Data quality issues
|
|
32
|
+
- Compliance gaps
|
|
33
|
+
|
|
34
|
+
Filter by domain, severity, status, etc.
|
|
35
|
+
"""
|
|
36
|
+
self.method = "POST"
|
|
37
|
+
self.endpoint = "/datagovernance/health/actions/query"
|
|
38
|
+
self.params = {"api-version": "2024-02-01-preview"}
|
|
39
|
+
|
|
40
|
+
# Build filter payload
|
|
41
|
+
payload = {}
|
|
42
|
+
|
|
43
|
+
domain_id = args.get("--domain-id", [""])[0]
|
|
44
|
+
if domain_id:
|
|
45
|
+
payload["domainId"] = domain_id
|
|
46
|
+
|
|
47
|
+
severity = args.get("--severity", [""])[0]
|
|
48
|
+
if severity:
|
|
49
|
+
payload["severity"] = severity
|
|
50
|
+
|
|
51
|
+
status = args.get("--status", [""])[0]
|
|
52
|
+
if status:
|
|
53
|
+
payload["status"] = status
|
|
54
|
+
|
|
55
|
+
finding_type = args.get("--finding-type", [""])[0]
|
|
56
|
+
if finding_type:
|
|
57
|
+
payload["findingType"] = finding_type
|
|
58
|
+
|
|
59
|
+
target_type = args.get("--target-entity-type", [""])[0]
|
|
60
|
+
if target_type:
|
|
61
|
+
payload["targetEntityType"] = target_type
|
|
62
|
+
|
|
63
|
+
self.payload = payload
|
|
64
|
+
|
|
65
|
+
@decorator
|
|
66
|
+
def get_health_action(self, args):
|
|
67
|
+
"""Get details of a specific health action by ID."""
|
|
68
|
+
action_id = args.get("--action-id", [""])[0]
|
|
69
|
+
|
|
70
|
+
self.method = "GET"
|
|
71
|
+
self.endpoint = f"/datagovernance/health/actions/{action_id}"
|
|
72
|
+
self.params = {"api-version": "2024-02-01-preview"}
|
|
73
|
+
|
|
74
|
+
@decorator
|
|
75
|
+
def update_health_action(self, args):
|
|
76
|
+
"""Update a health action (change status, assignment, etc.)."""
|
|
77
|
+
action_id = args.get("--action-id", [""])[0]
|
|
78
|
+
|
|
79
|
+
self.method = "PUT"
|
|
80
|
+
self.endpoint = f"/datagovernance/health/actions/{action_id}"
|
|
81
|
+
self.params = {"api-version": "2024-02-01-preview"}
|
|
82
|
+
|
|
83
|
+
payload = {}
|
|
84
|
+
|
|
85
|
+
status = args.get("--status", [""])[0]
|
|
86
|
+
if status:
|
|
87
|
+
payload["status"] = status
|
|
88
|
+
|
|
89
|
+
assigned_to = args.get("--assigned-to", [""])[0]
|
|
90
|
+
if assigned_to:
|
|
91
|
+
payload["assignedTo"] = [assigned_to] if assigned_to else []
|
|
92
|
+
|
|
93
|
+
reason = args.get("--reason", [""])[0]
|
|
94
|
+
if reason:
|
|
95
|
+
payload["reason"] = reason
|
|
96
|
+
|
|
97
|
+
self.payload = payload
|
|
98
|
+
|
|
99
|
+
@decorator
|
|
100
|
+
def delete_health_action(self, args):
|
|
101
|
+
"""Delete a health action."""
|
|
102
|
+
action_id = args.get("--action-id", [""])[0]
|
|
103
|
+
|
|
104
|
+
self.method = "DELETE"
|
|
105
|
+
self.endpoint = f"/datagovernance/health/actions/{action_id}"
|
|
106
|
+
self.params = {"api-version": "2024-02-01-preview"}
|
|
107
|
+
|
|
108
|
+
# ========================================
|
|
109
|
+
# STATISTICS & SUMMARIES
|
|
110
|
+
# ========================================
|
|
111
|
+
|
|
112
|
+
@decorator
|
|
113
|
+
def get_health_summary(self, args):
|
|
114
|
+
"""Get health summary statistics for a domain."""
|
|
115
|
+
domain_id = args.get("--domain-id", [""])[0]
|
|
116
|
+
|
|
117
|
+
self.method = "GET"
|
|
118
|
+
self.endpoint = "/datagovernance/health/summary"
|
|
119
|
+
self.params = {
|
|
120
|
+
"api-version": "2024-02-01-preview",
|
|
121
|
+
"domainId": domain_id
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# ========================================
|
|
125
|
+
# UTILITY METHODS
|
|
126
|
+
# ========================================
|
|
127
|
+
|
|
128
|
+
@no_api_call_decorator
|
|
129
|
+
def help(self, args):
|
|
130
|
+
"""Display help information for Health API operations."""
|
|
131
|
+
help_text = """
|
|
132
|
+
Microsoft Purview Health API Client
|
|
133
|
+
|
|
134
|
+
OVERVIEW:
|
|
135
|
+
The Health API provides automated governance monitoring and recommendations.
|
|
136
|
+
It identifies gaps in metadata, governance policies, and data quality.
|
|
137
|
+
|
|
138
|
+
OPERATIONS:
|
|
139
|
+
- query_health_actions: List all health findings with filters
|
|
140
|
+
- get_health_action: Get details of a specific finding
|
|
141
|
+
- update_health_action: Update status or assignment
|
|
142
|
+
- delete_health_action: Delete a finding
|
|
143
|
+
- get_health_summary: Get health statistics for a domain
|
|
144
|
+
|
|
145
|
+
HEALTH FINDING TYPES:
|
|
146
|
+
- Estate Curation: Critical data identification, classification
|
|
147
|
+
- Access and Use: Terms of use, compliant data use
|
|
148
|
+
- Discoverability: Data cataloging, term assignment
|
|
149
|
+
- Trusted Data: Data quality enablement
|
|
150
|
+
- Value Creation: Business OKRs alignment
|
|
151
|
+
- Metadata Quality Management: Description quality, completeness
|
|
152
|
+
|
|
153
|
+
SEVERITY LEVELS:
|
|
154
|
+
- High: Critical governance gaps
|
|
155
|
+
- Medium: Important improvements needed
|
|
156
|
+
- Low: Nice-to-have enhancements
|
|
157
|
+
|
|
158
|
+
STATUS VALUES:
|
|
159
|
+
- NotStarted: No action taken
|
|
160
|
+
- InProgress: Being addressed
|
|
161
|
+
- Resolved: Completed
|
|
162
|
+
- Dismissed: Acknowledged but not acting
|
|
163
|
+
|
|
164
|
+
FILTERS:
|
|
165
|
+
--domain-id: Filter by governance domain
|
|
166
|
+
--severity: High, Medium, Low
|
|
167
|
+
--status: NotStarted, InProgress, Resolved, Dismissed
|
|
168
|
+
--finding-type: Estate Curation, Access and Use, etc.
|
|
169
|
+
--target-entity-type: BusinessDomain, DataProduct, Term, etc.
|
|
170
|
+
|
|
171
|
+
EXAMPLES:
|
|
172
|
+
# List all health actions
|
|
173
|
+
pvcli health query
|
|
174
|
+
|
|
175
|
+
# List high severity issues
|
|
176
|
+
pvcli health query --severity High
|
|
177
|
+
|
|
178
|
+
# List actions for a specific domain
|
|
179
|
+
pvcli health query --domain-id xxx
|
|
180
|
+
|
|
181
|
+
# Get details of a specific action
|
|
182
|
+
pvcli health show --action-id xxx
|
|
183
|
+
|
|
184
|
+
# Mark action as in progress
|
|
185
|
+
pvcli health update --action-id xxx --status InProgress
|
|
186
|
+
|
|
187
|
+
# Assign action to a user
|
|
188
|
+
pvcli health update --action-id xxx --assigned-to user@domain.com
|
|
189
|
+
|
|
190
|
+
API VERSION: 2024-02-01-preview
|
|
191
|
+
"""
|
|
192
|
+
return {"message": help_text}
|