Skip to content

Commit 635f8bb

Browse files
author
Lo Ferris
committed
Merge branch 'notebook_ci' of github.com:GoogleCloudPlatform/python-docs-samples into notebook_ci
merging remote
2 parents cb04375 + 25d76ab commit 635f8bb

File tree

123 files changed

+2079
-543
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+2079
-543
lines changed

.cloud-build/CheckPythonVersion.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env python
2+
# # Copyright 2021 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
import sys
16+
17+
MINIMUM_MAJOR_VERSION = 3
18+
MINIMUM_MINOR_VERSION = 5
19+
20+
if (
21+
sys.version_info.major >= MINIMUM_MAJOR_VERSION
22+
or sys.version_info.minor >= MINIMUM_MINOR_VERSION
23+
):
24+
print(f"Python version acceptable: {sys.version}")
25+
exit(0)
26+
else:
27+
print(
28+
f"Error: Python version less than {MINIMUM_MAJOR_VERSION}.{MINIMUM_MINOR_VERSION}"
29+
)
30+
exit(1)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
steps:
2+
# Install Python dependencies and run cleanup script
3+
- name: ${_PYTHON_IMAGE}
4+
entrypoint: /bin/sh
5+
args:
6+
- -c
7+
- 'python3 -m pip install -U -r .cloud-build/cleanup/cleanup-requirements.txt && python3 .cloud-build/cleanup/cleanup.py'
8+
timeout: 86400s

.cloud-build/cleanup/cleanup.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env python
2+
# # Copyright 2022 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
from typing import List
17+
from resource_cleanup_manager import (
18+
ResourceCleanupManager,
19+
DatasetResourceCleanupManager,
20+
EndpointResourceCleanupManager,
21+
ModelResourceCleanupManager,
22+
)
23+
24+
25+
def run_cleanup_managers(managers: List[ResourceCleanupManager], is_dry_run: bool):
26+
for manager in managers:
27+
type_name = manager.type_name
28+
29+
print(f"Fetching {type_name}'s...")
30+
resources = manager.list()
31+
print(f"Found {len(resources)} {type_name}'s")
32+
for resource in resources:
33+
if not manager.is_deletable(resource):
34+
continue
35+
36+
if is_dry_run:
37+
resource_name = manager.resource_name(resource)
38+
print(f"Will delete '{type_name}': {resource_name}")
39+
else:
40+
try:
41+
manager.delete(resource)
42+
except Exception as exception:
43+
print(exception)
44+
45+
46+
is_dry_run = False
47+
48+
# List of all cleanup managers
49+
managers = [
50+
DatasetResourceCleanupManager(),
51+
EndpointResourceCleanupManager(),
52+
ModelResourceCleanupManager(),
53+
]
54+
55+
run_cleanup_managers(managers=managers, is_dry_run=is_dry_run)

.cloud-build/cleanup/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-cloud-aiplatform==1.12.1
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python
2+
# # Copyright 2022 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import abc
17+
from google.cloud import aiplatform
18+
from typing import Any
19+
from proto.datetime_helpers import DatetimeWithNanoseconds
20+
from google.cloud.aiplatform import base
21+
22+
# If a resource was updated within this number of seconds, do not delete.
23+
RESOURCE_UPDATE_BUFFER_IN_SECONDS = 60 * 60 * 8
24+
25+
26+
class ResourceCleanupManager(abc.ABC):
27+
@property
28+
@abc.abstractmethod
29+
def type_name(str) -> str:
30+
pass
31+
32+
@abc.abstractmethod
33+
def list(self) -> Any:
34+
pass
35+
36+
@abc.abstractmethod
37+
def resource_name(self, resource: Any) -> str:
38+
pass
39+
40+
@abc.abstractmethod
41+
def delete(self, resource: Any):
42+
pass
43+
44+
@abc.abstractmethod
45+
def get_seconds_since_modification(self, resource: Any) -> float:
46+
pass
47+
48+
def is_deletable(self, resource: Any) -> bool:
49+
time_difference = self.get_seconds_since_modification(resource)
50+
51+
if self.resource_name(resource).startswith("perm"):
52+
print(f"Skipping '{resource}' due to name starting with 'perm'.")
53+
return False
54+
55+
# Check that it wasn't created too recently, to prevent race conditions
56+
if time_difference <= RESOURCE_UPDATE_BUFFER_IN_SECONDS:
57+
print(
58+
f"Skipping '{resource}' due update_time being '{time_difference}', which is less than '{RESOURCE_UPDATE_BUFFER_IN_SECONDS}'."
59+
)
60+
return False
61+
62+
return True
63+
64+
65+
class VertexAIResourceCleanupManager(ResourceCleanupManager):
66+
@property
67+
@abc.abstractmethod
68+
def vertex_ai_resource(self) -> base.VertexAiResourceNounWithFutureManager:
69+
pass
70+
71+
@property
72+
def type_name(self) -> str:
73+
return self.vertex_ai_resource._resource_noun
74+
75+
def list(self) -> Any:
76+
return self.vertex_ai_resource.list()
77+
78+
def resource_name(self, resource: Any) -> str:
79+
return resource.display_name
80+
81+
def delete(self, resource):
82+
resource.delete()
83+
84+
def get_seconds_since_modification(self, resource: Any) -> bool:
85+
update_time = resource.update_time
86+
current_time = DatetimeWithNanoseconds.now(tz=update_time.tzinfo)
87+
return (current_time - update_time).total_seconds()
88+
89+
90+
class DatasetResourceCleanupManager(VertexAIResourceCleanupManager):
91+
vertex_ai_resource = aiplatform.datasets._Dataset
92+
93+
94+
class EndpointResourceCleanupManager(VertexAIResourceCleanupManager):
95+
vertex_ai_resource = aiplatform.Endpoint
96+
97+
def delete(self, resource):
98+
resource.delete(force=True)
99+
100+
101+
class ModelResourceCleanupManager(VertexAIResourceCleanupManager):
102+
vertex_ai_resource = aiplatform.Model
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env python
2+
# Copyright 2021 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""A CLI to process changed notebooks and execute them on Google Cloud Build"""
17+
18+
import argparse
19+
import pathlib
20+
import execute_changed_notebooks_helper
21+
22+
23+
def str2bool(v):
24+
if isinstance(v, bool):
25+
return v
26+
if v.lower() in ("yes", "true", "t", "y", "1"):
27+
return True
28+
elif v.lower() in ("no", "false", "f", "n", "0"):
29+
return False
30+
else:
31+
raise argparse.ArgumentTypeError("String value expected.")
32+
33+
34+
parser = argparse.ArgumentParser(description="Run changed notebooks.")
35+
parser.add_argument(
36+
"--test_paths_file",
37+
type=pathlib.Path,
38+
help="The path to the file that has newline-limited folders of notebooks that should be tested.",
39+
required=True,
40+
)
41+
parser.add_argument(
42+
"--base_branch",
43+
help="The base git branch to diff against to find changed files.",
44+
required=False,
45+
)
46+
parser.add_argument(
47+
"--container_uri",
48+
type=str,
49+
help="The container uri to run each notebook in.",
50+
required=True,
51+
)
52+
parser.add_argument(
53+
"--variable_project_id",
54+
type=str,
55+
help="The GCP project id. This is used to inject a variable value into the notebook before running.",
56+
required=True,
57+
)
58+
parser.add_argument(
59+
"--variable_region",
60+
type=str,
61+
help="The GCP region. This is used to inject a variable value into the notebook before running.",
62+
required=True,
63+
)
64+
parser.add_argument(
65+
"--staging_bucket",
66+
type=str,
67+
help="The GCS bucket for staging temporary files.",
68+
required=True,
69+
)
70+
parser.add_argument(
71+
"--artifacts_bucket",
72+
type=str,
73+
help="The GCP directory for storing executed notebooks.",
74+
required=True,
75+
)
76+
parser.add_argument(
77+
"--should_parallelize",
78+
type=str2bool,
79+
nargs="?",
80+
const=True,
81+
default=True,
82+
help="Should run notebooks in parallel.",
83+
)
84+
85+
args = parser.parse_args()
86+
87+
notebooks = execute_changed_notebooks_helper.get_changed_notebooks(
88+
test_paths_file=args.test_paths_file,
89+
base_branch=args.base_branch,
90+
)
91+
92+
execute_changed_notebooks_helper.process_and_execute_notebooks(
93+
notebooks=notebooks,
94+
container_uri=args.container_uri,
95+
staging_bucket=args.staging_bucket,
96+
artifacts_bucket=args.artifacts_bucket,
97+
variable_project_id=args.variable_project_id,
98+
variable_region=args.variable_region,
99+
should_parallelize=args.should_parallelize,
100+
)

0 commit comments

Comments
 (0)