Skip to content

Commit 4fe5495

Browse files
jacspa96Jacek Spalinskiiennaem-strzelczyk
authored
feat(dataplex): add code samples for Aspect Types (#12738)
* feat(dataplex): add sample for list Aspect Types * feat(dataplex): add sample for get Aspect Type * feat(dataplex): add sample for delete Aspect Type * feat(dataplex): add sample for create Aspect Type * feat(dataplex): add sample for update Aspect Type * feat(dataplex): add integration test for Aspect Types * feat(dataplex): add requirements files * feat(dataplex): add dataplex to code samples * fix: resolve error with user defined ownership * feat(dataplex): adjust test to use try/finally * feat(dataplex): change order of code owners Co-authored-by: Maciej Strzelczyk <[email protected]> --------- Co-authored-by: Jacek Spalinski <[email protected]> Co-authored-by: Jennifer Davis <[email protected]> Co-authored-by: Maciej Strzelczyk <[email protected]>
1 parent 1893171 commit 4fe5495

File tree

11 files changed

+411
-1
lines changed

11 files changed

+411
-1
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
# Platform Ops
3939
/monitoring/opencensus @yuriatgoogle @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
4040
/monitoring/prometheus @yuriatgoogle @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
41-
/trace/**/* @ymotongpoo @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
41+
/trace/**/* @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
4242

4343
# DEE Data & AI
4444
/speech/**/* @GoogleCloudPlatform/cloud-speech-eng @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
@@ -62,6 +62,7 @@
6262
/pubsub/**/* @GoogleCloudPlatform/api-pubsub-and-pubsublite @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
6363
/pubsublite/**/* @GoogleCloudPlatform/api-pubsub-and-pubsublite @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
6464
/managedkafka/**/* @GoogleCloudPlatform/api-pubsub-and-pubsublite @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
65+
/dataplex/**/* @GoogleCloudPlatform/googleapi-dataplex @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
6566

6667
# For practicing
6768
# ---* Use with codelabs to learn to submit samples

.github/auto-label.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ path:
3636
container-analysis: "containeranalysis"
3737
contentwarehouse: "contentwarehouse"
3838
datacatalog: "datacatalog"
39+
dataplex: "dataplex"
3940
datalabeling: "datalabeling"
4041
dataproc: "dataproc"
4142
datastore: "datastore"

.github/blunderbuss.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ assign_issues_by:
129129
- "api: serviceextensions"
130130
to:
131131
- GoogleCloudPlatform/service-extensions-samples-reviewers
132+
- labels:
133+
- "api: dataplex"
134+
to:
135+
- GoogleCloudPlatform/googleapi-dataplex
132136

133137
# Self-service individuals
134138
- labels:
@@ -250,6 +254,10 @@ assign_prs_by:
250254
to:
251255
- GoogleCloudPlatform/service-extensions-samples-reviewers
252256
- GoogleCloudPlatform/dee-infra
257+
- labels:
258+
- "api: dataplex"
259+
to:
260+
- GoogleCloudPlatform/googleapi-dataplex
253261
# Self-service individuals
254262
- labels:
255263
- "api: auth"
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
16+
import uuid
17+
18+
from google.api_core.retry import Retry
19+
20+
import pytest
21+
22+
import create_aspect_type
23+
import delete_aspect_type
24+
import get_aspect_type
25+
import list_aspect_types
26+
import update_aspect_type
27+
28+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
29+
LOCATION = "us-central1"
30+
ASPECT_TYPE_ID = f"test-aspect-type-{str(uuid.uuid4()).split('-')[0]}"
31+
EXPECTED_ASPECT_TYPE = (
32+
f"projects/{PROJECT_ID}/locations/{LOCATION}/aspectTypes/{ASPECT_TYPE_ID}"
33+
)
34+
35+
36+
@pytest.fixture(autouse=True, scope="session")
37+
def setup_and_teardown_aspect_type() -> None:
38+
try:
39+
# Create Aspect Type resource that will be used in tests for "get", "list" and "update" methods
40+
create_aspect_type.create_aspect_type(PROJECT_ID, LOCATION, ASPECT_TYPE_ID, [])
41+
yield
42+
finally:
43+
# Clean-up Aspect Type resource created above
44+
delete_aspect_type.delete_aspect_type(PROJECT_ID, LOCATION, ASPECT_TYPE_ID)
45+
46+
47+
@Retry()
48+
def test_list_aspect_types() -> None:
49+
aspect_types = list_aspect_types.list_aspect_types(PROJECT_ID, LOCATION)
50+
assert EXPECTED_ASPECT_TYPE in [aspect_type.name for aspect_type in aspect_types]
51+
52+
53+
@Retry()
54+
def test_get_aspect_type() -> None:
55+
aspect_type = get_aspect_type.get_aspect_type(PROJECT_ID, LOCATION, ASPECT_TYPE_ID)
56+
assert EXPECTED_ASPECT_TYPE == aspect_type.name
57+
58+
59+
@Retry()
60+
def test_update_aspect_type() -> None:
61+
aspect_type = update_aspect_type.update_aspect_type(
62+
PROJECT_ID, LOCATION, ASPECT_TYPE_ID, []
63+
)
64+
assert EXPECTED_ASPECT_TYPE == aspect_type.name
65+
66+
67+
@Retry()
68+
def test_create_aspect_type() -> None:
69+
aspect_type_id_to_create = f"test-aspect-type-{str(uuid.uuid4()).split('-')[0]}"
70+
expected_aspect_type_to_create = f"projects/{PROJECT_ID}/locations/{LOCATION}/aspectTypes/{aspect_type_id_to_create}"
71+
try:
72+
aspect_type = create_aspect_type.create_aspect_type(
73+
PROJECT_ID, LOCATION, aspect_type_id_to_create, []
74+
)
75+
assert expected_aspect_type_to_create == aspect_type.name
76+
finally:
77+
# Clean-up created Aspect Type
78+
delete_aspect_type.delete_aspect_type(
79+
PROJECT_ID, LOCATION, aspect_type_id_to_create
80+
)
81+
82+
83+
@Retry()
84+
def test_delete_aspect_type() -> None:
85+
aspect_type_id_to_delete = f"test-aspect-type-{str(uuid.uuid4()).split('-')[0]}"
86+
# Create Aspect Type to be deleted
87+
create_aspect_type.create_aspect_type(
88+
PROJECT_ID, LOCATION, aspect_type_id_to_delete, []
89+
)
90+
# No exception means successful call
91+
delete_aspect_type.delete_aspect_type(
92+
PROJECT_ID, LOCATION, aspect_type_id_to_delete
93+
)
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START dataplex_create_aspect_type]
16+
from typing import List
17+
18+
from google.cloud import dataplex_v1
19+
20+
21+
# Method to create Aspect Type located in project_id, location and with aspect_type_id and
22+
# aspect_fields specifying schema of the Aspect Type
23+
def create_aspect_type(
24+
project_id: str,
25+
location: str,
26+
aspect_type_id: str,
27+
aspect_fields: List[dataplex_v1.AspectType.MetadataTemplate],
28+
) -> dataplex_v1.AspectType:
29+
# Initialize client that will be used to send requests across threads. This
30+
# client only needs to be created once, and can be reused for multiple requests.
31+
# After completing all of your requests, call the "__exit__()" method to safely
32+
# clean up any remaining background resources. Alternatively, use the client as
33+
# a context manager.
34+
with dataplex_v1.CatalogServiceClient() as client:
35+
# The resource name of the Aspect Type location
36+
parent = f"projects/{project_id}/locations/{location}"
37+
aspect_type = dataplex_v1.AspectType(
38+
description="description of the aspect type",
39+
metadata_template=dataplex_v1.AspectType.MetadataTemplate(
40+
# The name must follow regex ^(([a-zA-Z]{1})([\\w\\-_]{0,62}))$
41+
# That means name must only contain alphanumeric character or dashes or underscores,
42+
# start with an alphabet, and must be less than 63 characters.
43+
name="name_of_the_template",
44+
type="record",
45+
# Aspect Type fields, that themselves are Metadata Templates.
46+
record_fields=aspect_fields,
47+
),
48+
)
49+
create_operation = client.create_aspect_type(
50+
parent=parent, aspect_type=aspect_type, aspect_type_id=aspect_type_id
51+
)
52+
return create_operation.result(60)
53+
54+
55+
if __name__ == "__main__":
56+
# TODO(developer): Replace these variables before running the sample.
57+
project_id = "MY_PROJECT_ID"
58+
# Available locations: https://cloud.google.com/dataplex/docs/locations
59+
location = "MY_LOCATION"
60+
aspect_type_id = "MY_ASPECT_TYPE_ID"
61+
aspect_field = dataplex_v1.AspectType.MetadataTemplate(
62+
# The name must follow regex ^(([a-zA-Z]{1})([\\w\\-_]{0,62}))$
63+
# That means name must only contain alphanumeric character or dashes or underscores,
64+
# start with an alphabet, and must be less than 63 characters.
65+
name="name_of_the_field",
66+
# Metadata Template is recursive structure,
67+
# primitive types such as "string" or "integer" indicate leaf node,
68+
# complex types such as "record" or "array" would require nested Metadata Template
69+
type="string",
70+
index=1,
71+
annotations=dataplex_v1.AspectType.MetadataTemplate.Annotations(
72+
description="description of the field"
73+
),
74+
constraints=dataplex_v1.AspectType.MetadataTemplate.Constraints(
75+
# Specifies if field will be required in Aspect Type.
76+
required=True
77+
),
78+
)
79+
aspect_fields = [aspect_field]
80+
81+
created_aspect_type = create_aspect_type(
82+
project_id, location, aspect_type_id, aspect_fields
83+
)
84+
print(f"Successfully created aspect type: {created_aspect_type.name}")
85+
# [END dataplex_create_aspect_type]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START dataplex_delete_aspect_type]
16+
from google.cloud import dataplex_v1
17+
18+
19+
# Method to delete Aspect Type located in project_id, location and with aspect_type_id
20+
def delete_aspect_type(project_id: str, location: str, aspect_type_id: str) -> None:
21+
# Initialize client that will be used to send requests across threads. This
22+
# client only needs to be created once, and can be reused for multiple requests.
23+
# After completing all of your requests, call the "__exit__()" method to safely
24+
# clean up any remaining background resources. Alternatively, use the client as
25+
# a context manager.
26+
with dataplex_v1.CatalogServiceClient() as client:
27+
# The resource name of the Aspect Type
28+
name = (
29+
f"projects/{project_id}/locations/{location}/aspectTypes/{aspect_type_id}"
30+
)
31+
client.delete_aspect_type(name=name)
32+
33+
34+
if __name__ == "__main__":
35+
# TODO(developer): Replace these variables before running the sample.
36+
project_id = "MY_PROJECT_ID"
37+
# Available locations: https://cloud.google.com/dataplex/docs/locations
38+
location = "MY_LOCATION"
39+
aspect_type_id = "MY_ASPECT_TYPE_ID"
40+
41+
delete_aspect_type(project_id, location, aspect_type_id)
42+
print("Successfully deleted aspect type")
43+
# [END dataplex_delete_aspect_type]
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START dataplex_get_aspect_type]
16+
from google.cloud import dataplex_v1
17+
18+
19+
# Method to retrieve Aspect Type located in project_id, location and with aspect_type_id
20+
def get_aspect_type(
21+
project_id: str, location: str, aspect_type_id: str
22+
) -> dataplex_v1.AspectType:
23+
# Initialize client that will be used to send requests across threads. This
24+
# client only needs to be created once, and can be reused for multiple requests.
25+
# After completing all of your requests, call the "__exit__()" method to safely
26+
# clean up any remaining background resources. Alternatively, use the client as
27+
# a context manager.
28+
with dataplex_v1.CatalogServiceClient() as client:
29+
# The resource name of the Aspect Type
30+
name = (
31+
f"projects/{project_id}/locations/{location}/aspectTypes/{aspect_type_id}"
32+
)
33+
return client.get_aspect_type(name=name)
34+
35+
36+
if __name__ == "__main__":
37+
# TODO(developer): Replace these variables before running the sample.
38+
project_id = "MY_PROJECT_ID"
39+
# Available locations: https://cloud.google.com/dataplex/docs/locations
40+
location = "MY_LOCATION"
41+
aspect_type_id = "MY_ASPECT_TYPE_ID"
42+
43+
aspect_type = get_aspect_type(project_id, location, aspect_type_id)
44+
print(f"Aspect type retrieved successfully: {aspect_type.name}")
45+
# [END dataplex_get_aspect_type]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START dataplex_list_aspect_types]
16+
from typing import List
17+
18+
from google.cloud import dataplex_v1
19+
20+
21+
# Method to list Aspect Types located in project_id and location
22+
def list_aspect_types(project_id: str, location: str) -> List[dataplex_v1.AspectType]:
23+
# Initialize client that will be used to send requests across threads. This
24+
# client only needs to be created once, and can be reused for multiple requests.
25+
# After completing all of your requests, call the "__exit__()" method to safely
26+
# clean up any remaining background resources. Alternatively, use the client as
27+
# a context manager.
28+
with dataplex_v1.CatalogServiceClient() as client:
29+
# The resource name of the Aspect Type location
30+
parent = f"projects/{project_id}/locations/{location}"
31+
results = client.list_aspect_types(parent=parent)
32+
return list(results)
33+
34+
35+
if __name__ == "__main__":
36+
# TODO(developer): Replace these variables before running the sample.
37+
project_id = "MY_PROJECT_ID"
38+
# Available locations: https://cloud.google.com/dataplex/docs/locations
39+
location = "MY_LOCATION"
40+
41+
aspect_types = list_aspect_types(project_id, location)
42+
for aspect_type in aspect_types:
43+
print(f"Aspect type name: {aspect_type.name}")
44+
# [END dataplex_list_aspect_types]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==8.3.3

dataplex/snippets/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-cloud-dataplex==2.2.2

0 commit comments

Comments
 (0)