pvw-cli 1.3.3__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.
- purviewcli/__init__.py +27 -0
- purviewcli/__main__.py +15 -0
- purviewcli/cli/__init__.py +5 -0
- purviewcli/cli/account.py +199 -0
- purviewcli/cli/cli.py +170 -0
- purviewcli/cli/collections.py +502 -0
- purviewcli/cli/domain.py +361 -0
- purviewcli/cli/entity.py +2436 -0
- purviewcli/cli/glossary.py +533 -0
- purviewcli/cli/health.py +250 -0
- purviewcli/cli/insight.py +113 -0
- purviewcli/cli/lineage.py +1103 -0
- purviewcli/cli/management.py +141 -0
- purviewcli/cli/policystore.py +103 -0
- purviewcli/cli/relationship.py +75 -0
- purviewcli/cli/scan.py +357 -0
- purviewcli/cli/search.py +527 -0
- purviewcli/cli/share.py +478 -0
- purviewcli/cli/types.py +831 -0
- purviewcli/cli/unified_catalog.py +3796 -0
- purviewcli/cli/workflow.py +402 -0
- purviewcli/client/__init__.py +21 -0
- purviewcli/client/_account.py +1877 -0
- purviewcli/client/_collections.py +1761 -0
- purviewcli/client/_domain.py +414 -0
- purviewcli/client/_entity.py +3545 -0
- purviewcli/client/_glossary.py +3233 -0
- purviewcli/client/_health.py +501 -0
- purviewcli/client/_insight.py +2873 -0
- purviewcli/client/_lineage.py +2138 -0
- purviewcli/client/_management.py +2202 -0
- purviewcli/client/_policystore.py +2915 -0
- purviewcli/client/_relationship.py +1351 -0
- purviewcli/client/_scan.py +2607 -0
- purviewcli/client/_search.py +1472 -0
- purviewcli/client/_share.py +272 -0
- purviewcli/client/_types.py +2708 -0
- purviewcli/client/_unified_catalog.py +5112 -0
- purviewcli/client/_workflow.py +2734 -0
- purviewcli/client/api_client.py +1295 -0
- purviewcli/client/business_rules.py +675 -0
- purviewcli/client/config.py +231 -0
- purviewcli/client/data_quality.py +433 -0
- purviewcli/client/endpoint.py +123 -0
- purviewcli/client/endpoints.py +554 -0
- purviewcli/client/exceptions.py +38 -0
- purviewcli/client/lineage_visualization.py +797 -0
- purviewcli/client/monitoring_dashboard.py +712 -0
- purviewcli/client/rate_limiter.py +30 -0
- purviewcli/client/retry_handler.py +125 -0
- purviewcli/client/scanning_operations.py +523 -0
- purviewcli/client/settings.py +1 -0
- purviewcli/client/sync_client.py +250 -0
- purviewcli/plugins/__init__.py +1 -0
- purviewcli/plugins/plugin_system.py +709 -0
- pvw_cli-1.3.3.dist-info/METADATA +1618 -0
- pvw_cli-1.3.3.dist-info/RECORD +60 -0
- pvw_cli-1.3.3.dist-info/WHEEL +5 -0
- pvw_cli-1.3.3.dist-info/entry_points.txt +3 -0
- pvw_cli-1.3.3.dist-info/top_level.txt +1 -0
purviewcli/cli/domain.py
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import json
|
|
3
|
+
from purviewcli.client._domain import Domain
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
console = Console()
|
|
7
|
+
|
|
8
|
+
@click.group(help="Governance domain management (Limited functionality - see individual commands for details). Governance domains are currently not fully available in the public Microsoft Purview REST API. Consider using collections as an alternative organizational structure.")
|
|
9
|
+
def domain():
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
@domain.command(help="Create a new governance domain. NOTE: This feature is not currently available in the public API. Use collections instead.")
|
|
13
|
+
@click.option("--name", required=True, help="The unique name of the governance domain")
|
|
14
|
+
@click.option("--friendly-name", help="A user-friendly display name for the domain")
|
|
15
|
+
@click.option("--description", help="Description of the governance domain")
|
|
16
|
+
@click.option("--payload-file", type=click.Path(exists=True), help="File path to a valid JSON document")
|
|
17
|
+
def create(name, friendly_name, description, payload_file):
|
|
18
|
+
"""Create a new governance domain."""
|
|
19
|
+
try:
|
|
20
|
+
args = {
|
|
21
|
+
'--name': name,
|
|
22
|
+
'--friendlyName': friendly_name,
|
|
23
|
+
'--description': description,
|
|
24
|
+
'--payloadFile': payload_file
|
|
25
|
+
}
|
|
26
|
+
client = Domain()
|
|
27
|
+
result = client.domainsCreate(args)
|
|
28
|
+
|
|
29
|
+
if result.get("status") == "not_available":
|
|
30
|
+
console.print(f"[yellow]LIMITATION:[/yellow] {result['message']}")
|
|
31
|
+
if result.get("suggested_action"):
|
|
32
|
+
console.print(f"[cyan]SUGGESTION:[/cyan] {result['suggested_action']}")
|
|
33
|
+
else:
|
|
34
|
+
console.print(f"[green]SUCCESS:[/green] Governance domain created: {name}")
|
|
35
|
+
console.print(json.dumps(result, indent=2))
|
|
36
|
+
except Exception as e:
|
|
37
|
+
console.print(f"[red]ERROR:[/red] Failed to create governance domain: {e}")
|
|
38
|
+
|
|
39
|
+
@domain.command(help="List all governance domains. NOTE: This feature is not currently available in the public API.")
|
|
40
|
+
def list():
|
|
41
|
+
"""List all governance domains."""
|
|
42
|
+
try:
|
|
43
|
+
client = Domain()
|
|
44
|
+
result = client.domainsList({})
|
|
45
|
+
|
|
46
|
+
if result.get("status") == "not_available":
|
|
47
|
+
console.print(f"[yellow]LIMITATION:[/yellow] {result['message']}")
|
|
48
|
+
console.print("\n[cyan]ALTERNATIVES:[/cyan]")
|
|
49
|
+
for alt in result.get("alternatives", []):
|
|
50
|
+
console.print(f" • {alt}")
|
|
51
|
+
console.print("\n[cyan]TRY INSTEAD:[/cyan] pvw collections list")
|
|
52
|
+
else:
|
|
53
|
+
console.print(json.dumps(result, indent=2))
|
|
54
|
+
except Exception as e:
|
|
55
|
+
console.print(f"[red]ERROR:[/red] Failed to list governance domains: {e}")
|
|
56
|
+
|
|
57
|
+
@domain.command(help="Get a governance domain by name. NOTE: This feature is not currently available in the public API.")
|
|
58
|
+
@click.option("--domain-name", required=True, help="The name of the governance domain")
|
|
59
|
+
def get(domain_name):
|
|
60
|
+
"""Get a governance domain by name."""
|
|
61
|
+
try:
|
|
62
|
+
args = {'--domainName': domain_name}
|
|
63
|
+
client = Domain()
|
|
64
|
+
result = client.domainsGet(args)
|
|
65
|
+
|
|
66
|
+
if result.get("status") == "not_available":
|
|
67
|
+
console.print(f"[yellow]LIMITATION:[/yellow] {result['message']}")
|
|
68
|
+
if result.get("suggested_action"):
|
|
69
|
+
console.print(f"[cyan]TRY INSTEAD:[/cyan] {result['suggested_action']}")
|
|
70
|
+
else:
|
|
71
|
+
console.print(json.dumps(result, indent=2))
|
|
72
|
+
except Exception as e:
|
|
73
|
+
console.print(f"[red]ERROR:[/red] Failed to get governance domain: {e}")
|
|
74
|
+
|
|
75
|
+
@domain.command(help="Update a governance domain's friendly name and/or description. NOTE: This feature is not currently available in the public API.")
|
|
76
|
+
@click.option("--domain-name", required=True, help="The name of the governance domain")
|
|
77
|
+
@click.option("--friendly-name", help="A new user-friendly display name for the domain")
|
|
78
|
+
@click.option("--description", help="A new description for the domain")
|
|
79
|
+
@click.option("--payload-file", type=click.Path(exists=True), help="File path to a valid JSON document")
|
|
80
|
+
def update(domain_name, friendly_name, description, payload_file):
|
|
81
|
+
"""Update a governance domain's friendly name and/or description."""
|
|
82
|
+
try:
|
|
83
|
+
args = {
|
|
84
|
+
'--domainName': domain_name,
|
|
85
|
+
'--friendlyName': friendly_name,
|
|
86
|
+
'--description': description,
|
|
87
|
+
'--payloadFile': payload_file
|
|
88
|
+
}
|
|
89
|
+
client = Domain()
|
|
90
|
+
result = client.domainsUpdate(args)
|
|
91
|
+
|
|
92
|
+
if result.get("status") == "not_available":
|
|
93
|
+
console.print(f"[yellow]LIMITATION:[/yellow] {result['message']}")
|
|
94
|
+
else:
|
|
95
|
+
console.print(f"[green]SUCCESS:[/green] Updated governance domain: {domain_name}")
|
|
96
|
+
console.print(json.dumps(result, indent=2))
|
|
97
|
+
except Exception as e:
|
|
98
|
+
console.print(f"[red]ERROR:[/red] Failed to update governance domain: {e}")
|
|
99
|
+
|
|
100
|
+
@domain.command(help="Delete a governance domain by name. NOTE: This feature is not currently available in the public API.")
|
|
101
|
+
@click.option("--domain-name", required=True, help="The name of the governance domain")
|
|
102
|
+
@click.option("--force", is_flag=True, help="Force deletion without confirmation")
|
|
103
|
+
def delete(domain_name, force):
|
|
104
|
+
"""Delete a governance domain by name."""
|
|
105
|
+
try:
|
|
106
|
+
if not force and not click.confirm(f"Are you sure you want to delete domain '{domain_name}'?"):
|
|
107
|
+
console.print("[yellow]Operation cancelled.[/yellow]")
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
args = {'--domainName': domain_name}
|
|
111
|
+
client = Domain()
|
|
112
|
+
result = client.domainsDelete(args)
|
|
113
|
+
|
|
114
|
+
if result.get("status") == "not_available":
|
|
115
|
+
console.print(f"[yellow]LIMITATION:[/yellow] {result['message']}")
|
|
116
|
+
else:
|
|
117
|
+
console.print(f"[green]SUCCESS:[/green] Deleted governance domain: {domain_name}")
|
|
118
|
+
console.print(json.dumps(result, indent=2))
|
|
119
|
+
except Exception as e:
|
|
120
|
+
console.print(f"[red]ERROR:[/red] Failed to delete governance domain: {e}")
|
|
121
|
+
|
|
122
|
+
@domain.command(help="Search for assets that might be related to governance domains using keywords like 'domain', entity attributes, or collections.")
|
|
123
|
+
@click.option("--keywords", help="Search keywords (e.g., 'finance domain', 'hr domain')")
|
|
124
|
+
@click.option("--entity-type", help="Entity type to search (e.g., 'DataSet', 'Table')")
|
|
125
|
+
@click.option("--collection", help="Search within a specific collection")
|
|
126
|
+
@click.option("--limit", type=int, default=25, help="Number of results to return")
|
|
127
|
+
def search(keywords, entity_type, collection, limit):
|
|
128
|
+
"""Search for assets that might contain domain-related information."""
|
|
129
|
+
try:
|
|
130
|
+
from purviewcli.client._search import Search
|
|
131
|
+
search_client = Search()
|
|
132
|
+
|
|
133
|
+
# Build search parameters
|
|
134
|
+
search_args = {}
|
|
135
|
+
|
|
136
|
+
# Build search keywords
|
|
137
|
+
search_terms = []
|
|
138
|
+
if keywords:
|
|
139
|
+
search_terms.append(keywords)
|
|
140
|
+
else:
|
|
141
|
+
# Default domain-related search terms
|
|
142
|
+
search_terms.append("domain governance business")
|
|
143
|
+
|
|
144
|
+
search_args['--keywords'] = ' '.join(search_terms)
|
|
145
|
+
search_args['--limit'] = limit
|
|
146
|
+
|
|
147
|
+
# Add filters if specified
|
|
148
|
+
filters = []
|
|
149
|
+
if entity_type:
|
|
150
|
+
filters.append(f'"objectType":"{entity_type}"')
|
|
151
|
+
if collection:
|
|
152
|
+
filters.append(f'"collection":"{collection}"')
|
|
153
|
+
|
|
154
|
+
if filters:
|
|
155
|
+
# Create a simple filter file content
|
|
156
|
+
filter_content = '{"and":[' + ','.join(['{' + f + '}' for f in filters]) + ']}'
|
|
157
|
+
console.print(f"[cyan]Search filters:[/cyan] {filter_content}")
|
|
158
|
+
|
|
159
|
+
console.print(f"[cyan]Searching for:[/cyan] {search_args['--keywords']}")
|
|
160
|
+
console.print("[yellow]Note:[/yellow] Looking for assets that might contain domain-related information...")
|
|
161
|
+
|
|
162
|
+
result = search_client.searchQuery(search_args)
|
|
163
|
+
|
|
164
|
+
if isinstance(result, dict) and result.get('value'):
|
|
165
|
+
console.print(f"\n[green]Found {len(result['value'])} potential results:[/green]")
|
|
166
|
+
for i, asset in enumerate(result['value'][:10]): # Show first 10 results
|
|
167
|
+
name = asset.get('name', 'Unknown')
|
|
168
|
+
asset_type = asset.get('assetType', ['Unknown'])[0] if asset.get('assetType') else 'Unknown'
|
|
169
|
+
qualified_name = asset.get('qualifiedName', 'N/A')
|
|
170
|
+
|
|
171
|
+
console.print(f"\n{i+1}. [bold]{name}[/bold] ({asset_type})")
|
|
172
|
+
console.print(f" Qualified Name: {qualified_name}")
|
|
173
|
+
|
|
174
|
+
# Look for domain-related attributes
|
|
175
|
+
if asset.get('description') and 'domain' in asset.get('description', '').lower():
|
|
176
|
+
console.print(f" [yellow]Description contains 'domain':[/yellow] {asset.get('description')}")
|
|
177
|
+
|
|
178
|
+
# Check for custom attributes that might contain domain info
|
|
179
|
+
if asset.get('businessAttributes'):
|
|
180
|
+
console.print(f" [cyan]Has business attributes that might contain domain info[/cyan]")
|
|
181
|
+
|
|
182
|
+
if len(result['value']) > 10:
|
|
183
|
+
console.print(f"\n[yellow]... and {len(result['value']) - 10} more results[/yellow]")
|
|
184
|
+
|
|
185
|
+
console.print(f"\n[cyan]Suggestions:[/cyan]")
|
|
186
|
+
console.print("• Look for assets with 'domain' in their description or business attributes")
|
|
187
|
+
console.print("• Use collections to organize assets by business domain")
|
|
188
|
+
console.print("• Consider adding custom entity attributes to track domain association")
|
|
189
|
+
|
|
190
|
+
else:
|
|
191
|
+
console.print("[yellow]No results found.[/yellow]")
|
|
192
|
+
console.print("\n[cyan]Try instead:[/cyan]")
|
|
193
|
+
console.print("• pvw search query --keywords 'your-domain-name'")
|
|
194
|
+
console.print("• pvw collections list # to see organizational structure")
|
|
195
|
+
console.print("• pvw entity read --guid <entity-guid> # to check specific entity attributes")
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
console.print(f"[red]ERROR:[/red] Failed to search for domain-related assets: {e}")
|
|
199
|
+
console.print("\n[cyan]Alternative commands:[/cyan]")
|
|
200
|
+
console.print("• pvw search query --keywords 'domain business'")
|
|
201
|
+
console.print("• pvw collections list")
|
|
202
|
+
|
|
203
|
+
@domain.command(name="check-attributes", help="Check existing entity types for domain-related attributes or see how to add domain tracking.")
|
|
204
|
+
def check_attributes():
|
|
205
|
+
"""Check what domain-related attributes might be available in entity types."""
|
|
206
|
+
try:
|
|
207
|
+
from purviewcli.client._types import Types
|
|
208
|
+
types_client = Types()
|
|
209
|
+
|
|
210
|
+
console.print("[cyan]Checking for domain-related capabilities...[/cyan]")
|
|
211
|
+
|
|
212
|
+
# Get entity type definitions to see if any have domain attributes
|
|
213
|
+
args = {'--typeName': 'DataSet'} # Check common entity type
|
|
214
|
+
result = types_client.typesRead(args)
|
|
215
|
+
|
|
216
|
+
console.print("\n[green]Current Options for Domain Organization:[/green]")
|
|
217
|
+
console.print("\n1. [bold]Collections[/bold] - Use as domain containers:")
|
|
218
|
+
console.print(" • pvw collections create --collection-name 'finance-domain'")
|
|
219
|
+
console.print(" • pvw collections create --collection-name 'hr-domain'")
|
|
220
|
+
|
|
221
|
+
console.print("\n2. [bold]Custom Attributes[/bold] - Add domain field to entities:")
|
|
222
|
+
console.print(" • Modify entity definitions to include 'domain' attribute")
|
|
223
|
+
console.print(" • Use business metadata to track domain association")
|
|
224
|
+
|
|
225
|
+
console.print("\n3. [bold]Glossary Terms[/bold] - Create domain vocabulary:")
|
|
226
|
+
console.print(" • pvw glossary createTerms --name 'Finance Domain'")
|
|
227
|
+
console.print(" • Assign domain terms to relevant assets")
|
|
228
|
+
|
|
229
|
+
console.print("\n4. [bold]Classifications[/bold] - Tag assets by domain:")
|
|
230
|
+
console.print(" • Create domain-specific classifications")
|
|
231
|
+
console.print(" • Apply to assets for domain grouping")
|
|
232
|
+
|
|
233
|
+
console.print("\n[yellow]Recommended Approach:[/yellow]")
|
|
234
|
+
console.print("Use collections as your primary domain organization structure:")
|
|
235
|
+
console.print("• Create a collection per business domain")
|
|
236
|
+
console.print("• Move/assign assets to appropriate domain collections")
|
|
237
|
+
console.print("• Use naming conventions like 'finance-domain', 'hr-domain'")
|
|
238
|
+
|
|
239
|
+
except Exception as e:
|
|
240
|
+
console.print(f"[yellow]INFO:[/yellow] Could not check entity types: {e}")
|
|
241
|
+
console.print("\n[green]Manual Domain Organization Options:[/green]")
|
|
242
|
+
console.print("1. Use collections as domain containers")
|
|
243
|
+
console.print("2. Add custom entity attributes for domain tracking")
|
|
244
|
+
console.print("3. Use glossary terms for domain vocabulary")
|
|
245
|
+
console.print("4. Apply domain-specific classifications")
|
|
246
|
+
|
|
247
|
+
@domain.command(help="Guide for creating domain-like structures using collections API")
|
|
248
|
+
@click.option("--domain-name", help="Suggested name for your domain-like collection")
|
|
249
|
+
@click.option("--show-examples", is_flag=True, help="Show detailed examples of domain patterns")
|
|
250
|
+
def create_using_collections(domain_name, show_examples):
|
|
251
|
+
"""Provides a step-by-step guide to create domain-like structures using collections."""
|
|
252
|
+
try:
|
|
253
|
+
console.print("\n[bold blue]📋 Creating Domain-like Structures with Microsoft Purview Collections[/bold blue]")
|
|
254
|
+
console.print("\n[yellow]OVERVIEW:[/yellow] Since governance domains are not available in the public API, you can use collections to create hierarchical, domain-like organizational structures.")
|
|
255
|
+
|
|
256
|
+
console.print("\n[cyan][*] COLLECTIONS AS DOMAINS - KEY CAPABILITIES:[/cyan]")
|
|
257
|
+
console.print("[OK] [green]Hierarchical Organization:[/green] Create nested collections up to 8 levels deep")
|
|
258
|
+
console.print("[OK] [green]Custom Naming:[/green] Use friendly names (up to 100 chars) and descriptions")
|
|
259
|
+
console.print("[OK] [green]Security Boundaries:[/green] Role-based access control per collection")
|
|
260
|
+
console.print("[OK] [green]Asset Organization:[/green] Group data sources, scans, and assets by business unit")
|
|
261
|
+
console.print("[OK] [green]Metadata Management:[/green] Organize metadata within business contexts")
|
|
262
|
+
|
|
263
|
+
if domain_name:
|
|
264
|
+
console.print(f"\n[cyan]🚀 CREATING DOMAIN-LIKE COLLECTION: '{domain_name}'[/cyan]")
|
|
265
|
+
console.print(f"1. [bold]Create top-level collection:[/bold]")
|
|
266
|
+
console.print(f" pvw collections create --collection-name {domain_name.lower().replace(' ', '-')} --friendly-name \"{domain_name}\" --description \"Top-level domain collection for {domain_name}\"")
|
|
267
|
+
|
|
268
|
+
console.print(f"\n2. [bold]Create sub-collections (departments/teams):[/bold]")
|
|
269
|
+
console.print(f" pvw collections create --collection-name {domain_name.lower().replace(' ', '-')}-finance --friendly-name \"{domain_name} Finance\" --parent-collection {domain_name.lower().replace(' ', '-')}")
|
|
270
|
+
console.print(f" pvw collections create --collection-name {domain_name.lower().replace(' ', '-')}-operations --friendly-name \"{domain_name} Operations\" --parent-collection {domain_name.lower().replace(' ', '-')}")
|
|
271
|
+
|
|
272
|
+
console.print("\n[cyan]📖 STEP-BY-STEP GUIDE:[/cyan]")
|
|
273
|
+
console.print("1. [bold]Plan Your Hierarchy:[/bold]")
|
|
274
|
+
console.print(" • Design your domain structure (departments, teams, projects)")
|
|
275
|
+
console.print(" • Consider security boundaries and access requirements")
|
|
276
|
+
console.print(" • Maximum 8 levels deep, up to 1000 collections total")
|
|
277
|
+
|
|
278
|
+
console.print("\n2. [bold]Create Root Domain Collection:[/bold]")
|
|
279
|
+
console.print(" pvw collections create --collection-name my-domain --friendly-name \"My Business Domain\" --description \"Root collection for business domain\"")
|
|
280
|
+
|
|
281
|
+
console.print("\n3. [bold]Create Department Sub-Collections:[/bold]")
|
|
282
|
+
console.print(" pvw collections create --collection-name my-domain-hr --friendly-name \"Human Resources\" --parent-collection my-domain")
|
|
283
|
+
console.print(" pvw collections create --collection-name my-domain-finance --friendly-name \"Finance Department\" --parent-collection my-domain")
|
|
284
|
+
|
|
285
|
+
console.print("\n4. [bold]Create Team/Project Collections:[/bold]")
|
|
286
|
+
console.print(" pvw collections create --collection-name my-domain-hr-payroll --friendly-name \"Payroll Team\" --parent-collection my-domain-hr")
|
|
287
|
+
|
|
288
|
+
if show_examples:
|
|
289
|
+
console.print("\n[cyan]💡 DOMAIN ORGANIZATION PATTERNS:[/cyan]")
|
|
290
|
+
|
|
291
|
+
console.print("\n[bold]🏢 Pattern 1: Business Unit Domains[/bold]")
|
|
292
|
+
console.print("```")
|
|
293
|
+
console.print("Healthcare-Organization (Root)")
|
|
294
|
+
console.print("├── Hospitals-Domain")
|
|
295
|
+
console.print("│ ├── Emergency-Services")
|
|
296
|
+
console.print("│ ├── Inpatient-Care")
|
|
297
|
+
console.print("│ └── Outpatient-Services")
|
|
298
|
+
console.print("├── Research-Domain")
|
|
299
|
+
console.print("│ ├── Clinical-Trials")
|
|
300
|
+
console.print("│ └── Medical-Research")
|
|
301
|
+
console.print("└── Administration-Domain")
|
|
302
|
+
console.print(" ├── HR-Systems")
|
|
303
|
+
console.print(" └── Finance-Systems")
|
|
304
|
+
console.print("```")
|
|
305
|
+
|
|
306
|
+
console.print("\n[bold]🌍 Pattern 2: Geographic Domains[/bold]")
|
|
307
|
+
console.print("```")
|
|
308
|
+
console.print("Global-Corporation (Root)")
|
|
309
|
+
console.print("├── North-America")
|
|
310
|
+
console.print("│ ├── US-Operations")
|
|
311
|
+
console.print("│ └── Canada-Operations")
|
|
312
|
+
console.print("├── Europe")
|
|
313
|
+
console.print("│ ├── UK-Operations")
|
|
314
|
+
console.print("│ └── Germany-Operations")
|
|
315
|
+
console.print("└── Asia-Pacific")
|
|
316
|
+
console.print(" ├── Japan-Operations")
|
|
317
|
+
console.print(" └── Australia-Operations")
|
|
318
|
+
console.print("```")
|
|
319
|
+
|
|
320
|
+
console.print("\n[bold]🔄 Pattern 3: Lifecycle/Environment Domains[/bold]")
|
|
321
|
+
console.print("```")
|
|
322
|
+
console.print("Data-Platform (Root)")
|
|
323
|
+
console.print("├── Development")
|
|
324
|
+
console.print("│ ├── Raw-Data")
|
|
325
|
+
console.print("│ ├── Processed-Data")
|
|
326
|
+
console.print("│ └── Analytics-Data")
|
|
327
|
+
console.print("├── Staging")
|
|
328
|
+
console.print("│ ├── Raw-Data")
|
|
329
|
+
console.print("│ └── Processed-Data")
|
|
330
|
+
console.print("└── Production")
|
|
331
|
+
console.print(" ├── Raw-Data")
|
|
332
|
+
console.print(" ├── Processed-Data")
|
|
333
|
+
console.print(" └── Analytics-Data")
|
|
334
|
+
console.print("```")
|
|
335
|
+
|
|
336
|
+
console.print("\n[cyan]🔐 ACCESS CONTROL & SECURITY:[/cyan]")
|
|
337
|
+
console.print("• Assign Collection Admin role for domain managers")
|
|
338
|
+
console.print("• Use Data Reader role for read-only access")
|
|
339
|
+
console.print("• Set Data Curator role for metadata management")
|
|
340
|
+
console.print("• Implement least-privilege access model")
|
|
341
|
+
|
|
342
|
+
console.print("\n[cyan][*] ADDITIONAL ORGANIZATION METHODS:[/cyan]")
|
|
343
|
+
console.print("• [bold]Custom Attributes:[/bold] Tag assets with domain information")
|
|
344
|
+
console.print("• [bold]Glossary Terms:[/bold] Create domain-specific business vocabularies")
|
|
345
|
+
console.print("• [bold]Classifications:[/bold] Apply domain-based data classifications")
|
|
346
|
+
|
|
347
|
+
console.print("\n[cyan]📝 USEFUL COMMANDS:[/cyan]")
|
|
348
|
+
console.print("• List all collections: [bold]pvw collections list[/bold]")
|
|
349
|
+
console.print("• Get collection details: [bold]pvw collections get --collection-name <name>[/bold]")
|
|
350
|
+
console.print("• Search domain assets: [bold]pvw domain search-assets --domain <domain-name>[/bold]")
|
|
351
|
+
console.print("• Check organization options: [bold]pvw domain check-attributes[/bold]")
|
|
352
|
+
|
|
353
|
+
console.print("\n[green][OK] NEXT STEPS:[/green]")
|
|
354
|
+
console.print("1. Plan your domain hierarchy based on your organization structure")
|
|
355
|
+
console.print("2. Create your root domain collection")
|
|
356
|
+
console.print("3. Add department and team sub-collections")
|
|
357
|
+
console.print("4. Set up appropriate access controls")
|
|
358
|
+
console.print("5. Register data sources under appropriate collections")
|
|
359
|
+
|
|
360
|
+
except Exception as e:
|
|
361
|
+
console.print(f"[red]ERROR:[/red] Failed to generate domain creation guide: {e}")
|