Skip to content

Commit f10a1d4

Browse files
fix: add resource manager utils to get project ID from project number (#1068)
* fix: add resource manager utils to get project ID from project number * fix: add docstring Co-authored-by: gcf-merge-on-green[bot] <60162190+gcf-merge-on-green[bot]@users.noreply.github.com>
1 parent bbe105d commit f10a1d4

File tree

5 files changed

+96
-16
lines changed

5 files changed

+96
-16
lines changed

google/cloud/aiplatform/featurestore/entity_type.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from google.cloud.aiplatform import featurestore
3434
from google.cloud.aiplatform import initializer
3535
from google.cloud.aiplatform import utils
36-
from google.cloud.aiplatform.utils import featurestore_utils
36+
from google.cloud.aiplatform.utils import featurestore_utils, resource_manager_utils
3737

3838
from google.cloud import bigquery
3939

@@ -1259,10 +1259,11 @@ def ingest_from_df(
12591259
"-", "_"
12601260
)
12611261

1262-
# TODO(b/216497263): Add support for resource project does not match initializer.global_config.project
1263-
temp_bq_dataset_id = f"{initializer.global_config.project}.{temp_bq_dataset_name}"[
1264-
:1024
1265-
]
1262+
project_id = resource_manager_utils.get_project_id(
1263+
project_number=entity_type_name_components["project"],
1264+
credentials=self.credentials,
1265+
)
1266+
temp_bq_dataset_id = f"{project_id}.{temp_bq_dataset_name}"[:1024]
12661267
temp_bq_table_id = f"{temp_bq_dataset_id}.{entity_type_id}"
12671268

12681269
temp_bq_dataset = bigquery.Dataset(dataset_ref=temp_bq_dataset_id)

google/cloud/aiplatform/featurestore/featurestore.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from google.cloud.aiplatform import featurestore
3232
from google.cloud.aiplatform import initializer
3333
from google.cloud.aiplatform import utils
34-
from google.cloud.aiplatform.utils import featurestore_utils
34+
from google.cloud.aiplatform.utils import featurestore_utils, resource_manager_utils
3535

3636
from google.cloud import bigquery
3737

@@ -1147,10 +1147,11 @@ def batch_serve_to_df(
11471147
"-", "_"
11481148
)
11491149

1150-
# TODO(b/216497263): Add support for resource project does not match initializer.global_config.project
1151-
temp_bq_dataset_id = f"{initializer.global_config.project}.{temp_bq_dataset_name}"[
1152-
:1024
1153-
]
1150+
project_id = resource_manager_utils.get_project_id(
1151+
project_number=featurestore_name_components["project"],
1152+
credentials=self.credentials,
1153+
)
1154+
temp_bq_dataset_id = f"{project_id}.{temp_bq_dataset_name}"[:1024]
11541155
temp_bq_dataset = bigquery.Dataset(dataset_ref=temp_bq_dataset_id)
11551156
temp_bq_dataset.location = self.location
11561157
temp_bq_dataset = bigquery_client.create_dataset(temp_bq_dataset)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Copyright 2022 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
19+
from typing import Optional
20+
21+
from google.auth import credentials as auth_credentials
22+
from google.cloud import resourcemanager
23+
24+
from google.cloud.aiplatform import initializer
25+
26+
27+
def get_project_id(
28+
project_number: str, credentials: Optional[auth_credentials.Credentials] = None,
29+
) -> str:
30+
"""Gets project ID given the project number
31+
32+
Args:
33+
project_number (str):
34+
Required. The automatically generated unique identifier for your GCP project.
35+
credentials: The custom credentials to use when making API calls.
36+
Optional. If not provided, default credentials will be used.
37+
38+
Returns:
39+
str - The unique string used to differentiate your GCP project from all others in Google Cloud.
40+
41+
"""
42+
43+
credentials = credentials or initializer.global_config.credentials
44+
45+
projects_client = resourcemanager.ProjectsClient(credentials=credentials)
46+
47+
project = projects_client.get_project(name=f"projects/{project_number}")
48+
49+
return project.project_id

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"packaging >= 14.3",
101101
"google-cloud-storage >= 1.32.0, < 3.0.0dev",
102102
"google-cloud-bigquery >= 1.15.0, < 3.0.0dev",
103+
"google-cloud-resource-manager >= 1.3.3, < 3.0.0dev",
103104
),
104105
extras_require={
105106
"full": full_extra_require,

tests/unit/aiplatform/test_featurestores.py

+34-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from google.cloud.aiplatform import base
3333
from google.cloud.aiplatform import initializer
3434
from google.cloud.aiplatform import utils
35+
from google.cloud.aiplatform.utils import resource_manager_utils
3536

3637
from google.cloud.aiplatform.utils import featurestore_utils
3738
from google.cloud.aiplatform_v1.services.featurestore_service import (
@@ -54,11 +55,13 @@
5455

5556
from google.cloud import bigquery
5657
from google.cloud import bigquery_storage
58+
from google.cloud import resourcemanager
5759

5860
from google.cloud.bigquery_storage_v1.types import stream as gcbqs_stream
5961

6062
# project
6163
_TEST_PROJECT = "test-project"
64+
_TEST_PROJECT_DIFF = "test-project-diff"
6265
_TEST_LOCATION = "us-central1"
6366
_TEST_PARENT = f"projects/{_TEST_PROJECT}/locations/{_TEST_LOCATION}"
6467

@@ -340,6 +343,18 @@ def uuid_mock():
340343
return uuid.UUID(int=1)
341344

342345

346+
# All Resource Manager Mocks
347+
@pytest.fixture
348+
def get_project_mock():
349+
with patch.object(
350+
resourcemanager.ProjectsClient, "get_project"
351+
) as get_project_mock:
352+
get_project_mock.return_value = resourcemanager.Project(
353+
project_id=_TEST_PROJECT,
354+
)
355+
yield get_project_mock
356+
357+
343358
# All BigQuery Mocks
344359
@pytest.fixture
345360
def bq_client_mock():
@@ -1286,10 +1301,13 @@ def test_batch_serve_to_gcs_with_invalid_gcs_destination_type(self):
12861301
"bq_delete_dataset_mock",
12871302
"bqs_init_client_mock",
12881303
"bqs_create_read_session",
1304+
"get_project_mock",
12891305
)
12901306
@patch("uuid.uuid4", uuid_mock)
12911307
def test_batch_serve_to_df(self, batch_read_feature_values_mock):
1292-
aiplatform.init(project=_TEST_PROJECT)
1308+
1309+
aiplatform.init(project=_TEST_PROJECT_DIFF)
1310+
12931311
my_featurestore = aiplatform.Featurestore(
12941312
featurestore_name=_TEST_FEATURESTORE_NAME
12951313
)
@@ -1299,7 +1317,7 @@ def test_batch_serve_to_df(self, batch_read_feature_values_mock):
12991317
expected_temp_bq_dataset_name = f"temp_{_TEST_FEATURESTORE_ID}_{uuid.uuid4()}".replace(
13001318
"-", "_"
13011319
)
1302-
expecte_temp_bq_dataset_id = f"{initializer.global_config.project}.{expected_temp_bq_dataset_name}"[
1320+
expecte_temp_bq_dataset_id = f"{_TEST_PROJECT}.{expected_temp_bq_dataset_name}"[
13031321
:1024
13041322
]
13051323
expected_temp_bq_read_instances_table_id = (
@@ -1695,6 +1713,7 @@ def test_ingest_from_gcs_with_invalid_gcs_source_type(self):
16951713
"bq_init_dataset_mock",
16961714
"bq_create_dataset_mock",
16971715
"bq_delete_dataset_mock",
1716+
"get_project_mock",
16981717
)
16991718
@patch("uuid.uuid4", uuid_mock)
17001719
def test_ingest_from_df_using_column(
@@ -1704,7 +1723,7 @@ def test_ingest_from_df_using_column(
17041723
bq_init_schema_field_mock,
17051724
):
17061725

1707-
aiplatform.init(project=_TEST_PROJECT)
1726+
aiplatform.init(project=_TEST_PROJECT_DIFF)
17081727

17091728
my_entity_type = aiplatform.EntityType(entity_type_name=_TEST_ENTITY_TYPE_NAME)
17101729
df_source = pd.DataFrame()
@@ -1717,7 +1736,7 @@ def test_ingest_from_df_using_column(
17171736
expected_temp_bq_dataset_name = f"temp_{_TEST_FEATURESTORE_ID}_{uuid.uuid4()}".replace(
17181737
"-", "_"
17191738
)
1720-
expecte_temp_bq_dataset_id = f"{initializer.global_config.project}.{expected_temp_bq_dataset_name}"[
1739+
expecte_temp_bq_dataset_id = f"{_TEST_PROJECT}.{expected_temp_bq_dataset_name}"[
17211740
:1024
17221741
]
17231742
expected_temp_bq_table_id = (
@@ -1755,6 +1774,7 @@ def test_ingest_from_df_using_column(
17551774
"bq_init_dataset_mock",
17561775
"bq_create_dataset_mock",
17571776
"bq_delete_dataset_mock",
1777+
"get_project_mock",
17581778
)
17591779
@patch("uuid.uuid4", uuid_mock)
17601780
def test_ingest_from_df_using_datetime(
@@ -1763,7 +1783,8 @@ def test_ingest_from_df_using_datetime(
17631783
bq_load_table_from_dataframe_mock,
17641784
bq_init_schema_field_mock,
17651785
):
1766-
aiplatform.init(project=_TEST_PROJECT)
1786+
1787+
aiplatform.init(project=_TEST_PROJECT_DIFF)
17671788

17681789
my_entity_type = aiplatform.EntityType(entity_type_name=_TEST_ENTITY_TYPE_NAME)
17691790
df_source = pd.DataFrame()
@@ -1777,7 +1798,7 @@ def test_ingest_from_df_using_datetime(
17771798
expected_temp_bq_dataset_name = f"temp_{_TEST_FEATURESTORE_ID}_{uuid.uuid4()}".replace(
17781799
"-", "_"
17791800
)
1780-
expecte_temp_bq_dataset_id = f"{initializer.global_config.project}.{expected_temp_bq_dataset_name}"[
1801+
expecte_temp_bq_dataset_id = f"{_TEST_PROJECT}.{expected_temp_bq_dataset_name}"[
17811802
:1024
17821803
]
17831804
expected_temp_bq_table_id = (
@@ -2431,3 +2452,10 @@ def test_create_feature(self, create_feature_mock, sync):
24312452
),
24322453
metadata=_TEST_REQUEST_METADATA,
24332454
)
2455+
2456+
2457+
class TestResourceManagerUtils:
2458+
@pytest.mark.usefixtures("get_project_mock")
2459+
def test_get_project_id(self):
2460+
project_id = resource_manager_utils.get_project_id(project_number="123456")
2461+
assert project_id == _TEST_PROJECT

0 commit comments

Comments
 (0)