-
Notifications
You must be signed in to change notification settings - Fork 95
Add sagemaker integration tests #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
86a9df4
e422eb3
15a9b7c
3323df8
9ca1ecc
a205e1e
411d6a1
1ff8724
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
| # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
| # ANY KIND, either express or implied. See the License for the specific | ||
| # language governing permissions and limitations under the License. | ||
| import boto3 | ||
| import os | ||
| import logging | ||
| import platform | ||
|
|
@@ -18,7 +19,7 @@ | |
| import sys | ||
| import tempfile | ||
|
|
||
|
|
||
| from sagemaker import Session | ||
| from test.utils import local_mode | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
@@ -36,6 +37,8 @@ | |
| def pytest_addoption(parser): | ||
| parser.addoption('--build-image', '-D', action="store_true") | ||
| parser.addoption('--build-base-image', '-B', action="store_true") | ||
| parser.addoption('--aws-id') | ||
| parser.addoption('--instance-type') | ||
| parser.addoption('--install-container-support', '-C', action="store_true") | ||
| parser.addoption('--docker-base-name', default='pytorch') | ||
| parser.addoption('--region', default='us-west-2') | ||
|
|
@@ -46,40 +49,40 @@ def pytest_addoption(parser): | |
| parser.addoption('--tag', default=None) | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def docker_base_name(request): | ||
| @pytest.fixture(scope='session', name='docker_base_name') | ||
| def fixture_docker_base_name(request): | ||
| return request.config.getoption('--docker-base-name') | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def region(request): | ||
| @pytest.fixture(scope='session', name='region') | ||
| def fixture_region(request): | ||
| return request.config.getoption('--region') | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def framework_version(request): | ||
| @pytest.fixture(scope='session', name='framework_version') | ||
| def fixture_framework_version(request): | ||
| return request.config.getoption('--framework-version') | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def py_version(request): | ||
| @pytest.fixture(scope='session', name='py_version') | ||
| def fixture_py_version(request): | ||
| return 'py{}'.format(int(request.config.getoption('--py-version'))) | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def processor(request): | ||
| @pytest.fixture(scope='session', name='processor') | ||
| def fixture_processor(request): | ||
| return request.config.getoption('--processor') | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def tag(request, framework_version, processor, py_version): | ||
| @pytest.fixture(scope='session', name='tag') | ||
| def fixture_tag(request, framework_version, processor, py_version): | ||
| provided_tag = request.config.getoption('--tag') | ||
| default_tag = '{}-{}-{}'.format(framework_version, processor, py_version) | ||
| return provided_tag if provided_tag else default_tag | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def docker_image(docker_base_name, tag): | ||
| @pytest.fixture(scope='session', name='docker_image') | ||
| def fixture_docker_image(docker_base_name, tag): | ||
| return '{}:{}'.format(docker_base_name, tag) | ||
|
|
||
|
|
||
|
|
@@ -96,20 +99,20 @@ def opt_ml(): | |
| shutil.rmtree(tmp, True) | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session') | ||
| def use_gpu(processor): | ||
| @pytest.fixture(scope='session', name='use_gpu') | ||
| def fixture_use_gpu(processor): | ||
| return processor == 'gpu' | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session', autouse=True) | ||
| def install_container_support(request): | ||
| @pytest.fixture(scope='session', name='install_container_support', autouse=True) | ||
| def fixture_install_container_support(request): | ||
| install = request.config.getoption('--install-container-support') | ||
| if install: | ||
| local_mode.install_container_support() | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session', autouse=True) | ||
| def build_base_image(request, framework_version, py_version, processor, tag, docker_base_name): | ||
| @pytest.fixture(scope='session', name='build_base_image', autouse=True) | ||
| def fixture_build_base_image(request, framework_version, py_version, processor, tag, docker_base_name): | ||
| build_base_image = request.config.getoption('--build-base-image') | ||
| if build_base_image: | ||
| return local_mode.build_base_image(framework_name=docker_base_name, | ||
|
|
@@ -122,8 +125,8 @@ def build_base_image(request, framework_version, py_version, processor, tag, doc | |
| return tag | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session', autouse=True) | ||
| def build_image(request, framework_version, py_version, processor, tag, docker_base_name): | ||
| @pytest.fixture(scope='session', name='build_image', autouse=True) | ||
| def fixture_build_image(request, framework_version, py_version, processor, tag, docker_base_name): | ||
| build_image = request.config.getoption('--build-image') | ||
| if build_image: | ||
| return local_mode.build_image(framework_name=docker_base_name, | ||
|
|
@@ -134,3 +137,38 @@ def build_image(request, framework_version, py_version, processor, tag, docker_b | |
| cwd=os.path.join(dir_path, '..')) | ||
|
|
||
| return tag | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session', name='sagemaker_session') | ||
| def fixture_sagemaker_session(region): | ||
| return Session(boto_session=boto3.Session(region_name=region)) | ||
|
|
||
|
|
||
| @pytest.fixture(name='aws_id', scope='session') | ||
| def fixture_aws_id(request): | ||
| return request.config.getoption('--aws-id') | ||
|
|
||
|
|
||
| @pytest.fixture(name='instance_type', scope='session') | ||
| def fixture_instance_type(request): | ||
| return request.config.getoption('--instance-type') | ||
|
|
||
|
|
||
| @pytest.fixture(name='docker_registry', scope='session') | ||
| def fixture_docker_registry(aws_id, region): | ||
| return '{}.dkr.ecr.{}.amazonaws.com'.format(aws_id, region) | ||
|
|
||
|
|
||
| @pytest.fixture(name='ecr_image', scope='session') | ||
| def fixture_ecr_image(docker_registry, docker_base_name, tag): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will run sagemaker integ tests with repo sagemaker-pytorch, right? but i think integ tests push to preprod-pytorch. i'm not sure if this will run against the image pushed after local tests.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's a good point! |
||
| return '{}/{}:{}'.format(docker_registry, docker_base_name, tag) | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session', name='dist_cpu_backend', params=['tcp', 'gloo']) | ||
| def fixture_dist_cpu_backend(request): | ||
| return request.param | ||
|
|
||
|
|
||
| @pytest.fixture(scope='session', name='dist_gpu_backend', params=['gloo']) | ||
| def fixture_dist_gpu_backend(request): | ||
| return request.param | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"). You | ||
| # may not use this file except in compliance with the License. A copy of | ||
| # the License is located at | ||
| # | ||
| # http://aws.amazon.com/apache2.0/ | ||
| # | ||
| # or in the "license" file accompanying this file. This file is | ||
| # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
| # ANY KIND, either express or implied. See the License for the specific | ||
| # language governing permissions and limitations under the License. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"). You | ||
| # may not use this file except in compliance with the License. A copy of | ||
| # the License is located at | ||
| # | ||
| # http://aws.amazon.com/apache2.0/ | ||
| # | ||
| # or in the "license" file accompanying this file. This file is | ||
| # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
| # ANY KIND, either express or implied. See the License for the specific | ||
| # language governing permissions and limitations under the License. | ||
| import pytest | ||
|
|
||
|
|
||
| @pytest.fixture(autouse=True) | ||
| def skip_by_device_type(request, tag): | ||
| if (request.node.get_marker('skip_gpu') and 'gpu' in tag) or (request.node.get_marker('skip_cpu') and 'cpu' in tag): | ||
| pytest.skip('Skipping because tag is: {}'.format(tag)) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"). You | ||
| # may not use this file except in compliance with the License. A copy of | ||
| # the License is located at | ||
| # | ||
| # http://aws.amazon.com/apache2.0/ | ||
| # | ||
| # or in the "license" file accompanying this file. This file is | ||
| # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
| # ANY KIND, either express or implied. See the License for the specific | ||
| # language governing permissions and limitations under the License. | ||
| from sagemaker.pytorch.estimator import PyTorch | ||
|
|
||
|
|
||
| class PytorchTestEstimator(PyTorch): | ||
| def __init__(self, docker_image_uri, **kwargs): | ||
| super(PytorchTestEstimator, self).__init__(**kwargs) | ||
| self.docker_image_uri = docker_image_uri | ||
|
|
||
| def train_image(self): | ||
| return self.docker_image_uri | ||
|
|
||
| def create_model(self): | ||
| model = super(PytorchTestEstimator, self).create_model() | ||
| model.image = self.docker_image_uri | ||
| return model |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just asking: why is this new way preferred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid pylint's warning about "Shadows name from outer scope".
http://blog.pytest.org/2016/whats-new-in-pytest-30/ Fixture name parameter:
"This solves the problem where the function argument shadows the argument name, which annoys pylint and might cause bugs if one forgets to pull a fixture into a test function."