Skip to content
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

use get application API when calling get_rstudio_app_info #468

Merged
merged 7 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Fixed
- Error deploying to shinyapps.io when `--app-id` is provided [#464](https://github.com/rstudio/rsconnect-python/issues/464).

### Added

- Add `--disable-env-management`, `--disable-env-management-py` and `--disable-env-management-r` flags for all content types
Expand Down
13 changes: 8 additions & 5 deletions rsconnect/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def deploy(self, app_id, app_name, app_title, title_is_default, tarball, env_var
try:
self._server.handle_bad_response(app)
except RSConnectException as e:
raise RSConnectException(f"{e} Try setting the --new flag to overwrite the previous deployment.")
raise RSConnectException(f"{e} Try setting the --new flag to overwrite the previous deployment.") from e

app_guid = app["guid"]
if env_vars:
Expand Down Expand Up @@ -847,15 +847,15 @@ def validate_app_mode(self, *args, **kwargs):
except RSConnectException as e:
raise RSConnectException(
f"{e} Try setting the --new flag to overwrite the previous deployment."
)
) from e
elif isinstance(self.remote_server, PositServer):
try:
app = get_rstudio_app_info(self.remote_server, app_id)
existing_app_mode = AppModes.get_by_cloud_name(app["mode"])
except RSConnectException as e:
raise RSConnectException(
f"{e} Try setting the --new flag to overwrite the previous deployment."
)
) from e
else:
raise RSConnectException("Unable to infer Connect client.")
if existing_app_mode and existing_app_mode not in (None, AppModes.UNKNOWN, app_mode):
Expand Down Expand Up @@ -1485,8 +1485,11 @@ def get_app_info(connect_server, app_id):

def get_rstudio_app_info(server, app_id):
with PositClient(server) as client:
response = client.get_content(app_id)
return response["source"]
if isinstance(server, ShinyappsServer):
return client.get_application(app_id)
else:
response = client.get_content(app_id)
return response["source"]


def get_app_config(connect_server, app_id):
Expand Down
168 changes: 167 additions & 1 deletion tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def post_application_callback(request, uri, response_headers):
return [
201,
{"Content-Type": "application/json"},
open("tests/testdata/rstudio-responses/create-application.json", "r").read(),
open("tests/testdata/rstudio-responses/application.json", "r").read(),
]

httpretty.register_uri(
Expand Down Expand Up @@ -278,6 +278,172 @@ def post_deploy_callback(request, uri, response_headers):
if original_server_value:
os.environ["CONNECT_SERVER"] = original_server_value

@httpretty.activate(verbose=True, allow_net_connect=False)
def test_redeploy_manifest_shinyapps(self):
original_api_key_value = os.environ.pop("CONNECT_API_KEY", None)
original_server_value = os.environ.pop("CONNECT_SERVER", None)

httpretty.register_uri(
httpretty.GET,
"https://api.shinyapps.io/v1/users/me",
body=open("tests/testdata/rstudio-responses/get-user.json", "r").read(),
status=200,
)
httpretty.register_uri(
httpretty.GET,
"https://api.shinyapps.io/v1/applications"
"?filter=name:like:shinyapp&offset=0&count=100&use_advanced_filters=true",
body=open("tests/testdata/rstudio-responses/get-applications.json", "r").read(),
adding_headers={"Content-Type": "application/json"},
status=200,
)
httpretty.register_uri(
httpretty.GET,
"https://api.shinyapps.io/v1/accounts/",
body=open("tests/testdata/rstudio-responses/get-accounts.json", "r").read(),
adding_headers={"Content-Type": "application/json"},
status=200,
)

httpretty.register_uri(
httpretty.GET,
"https://api.shinyapps.io/v1/applications/8442",
body=open("tests/testdata/rstudio-responses/application.json", "r").read(),
adding_headers={"Content-Type": "application/json"},
status=200,
)

def post_application_property_callback(request, uri, response_headers):
parsed_request = _load_json(request.body)
try:
assert parsed_request == {"value": "private"}
except AssertionError as e:
return _error_to_response(e)
return [
201,
{},
b"",
]

httpretty.register_uri(
httpretty.PUT,
"https://api.shinyapps.io/v1/applications/8442/properties/application.visibility",
body=post_application_property_callback,
status=200,
)

def post_bundle_callback(request, uri, response_headers):
parsed_request = _load_json(request.body)
del parsed_request["checksum"]
del parsed_request["content_length"]
try:
assert parsed_request == {
"application": 8442,
"content_type": "application/x-tar",
}
except AssertionError as e:
return _error_to_response(e)
return [
201,
{"Content-Type": "application/json"},
open("tests/testdata/rstudio-responses/create-bundle.json", "r").read(),
]

httpretty.register_uri(
httpretty.POST,
"https://api.shinyapps.io/v1/bundles",
body=post_bundle_callback,
)

httpretty.register_uri(
httpretty.PUT,
"https://lucid-uploads-staging.s3.amazonaws.com/bundles/application-8442/"
"6c9ed0d91ee9426687d9ac231d47dc83.tar.gz"
"?AWSAccessKeyId=theAccessKeyId"
"&Signature=dGhlU2lnbmF0dXJlCg%3D%3D"
"&content-md5=D1blMI4qTiI3tgeUOYXwkg%3D%3D"
"&content-type=application%2Fx-tar"
"&x-amz-security-token=dGhlVG9rZW4K"
"&Expires=1656715153",
body="",
)

def post_bundle_status_callback(request, uri, response_headers):
parsed_request = _load_json(request.body)
try:
assert parsed_request == {"status": "ready"}
except AssertionError as e:
return _error_to_response(e)
return [303, {"Location": "https://api.shinyapps.io/v1/bundles/12640"}, ""]

httpretty.register_uri(
httpretty.POST,
"https://api.shinyapps.io/v1/bundles/12640/status",
body=post_bundle_status_callback,
)

httpretty.register_uri(
httpretty.GET,
"https://api.shinyapps.io/v1/bundles/12640",
body=open("tests/testdata/rstudio-responses/get-accounts.json", "r").read(),
adding_headers={"Content-Type": "application/json"},
status=200,
)

def post_deploy_callback(request, uri, response_headers):
parsed_request = _load_json(request.body)
try:
assert parsed_request == {"bundle": 12640, "rebuild": False}
except AssertionError as e:
return _error_to_response(e)
return [
303,
{"Location": "https://api.shinyapps.io/v1/tasks/333"},
open("tests/testdata/rstudio-responses/post-deploy.json", "r").read(),
]

httpretty.register_uri(
httpretty.POST,
"https://api.shinyapps.io/v1/applications/8442/deploy",
body=post_deploy_callback,
)

httpretty.register_uri(
httpretty.GET,
"https://api.shinyapps.io/v1/tasks/333",
body=open("tests/testdata/rstudio-responses/get-task.json", "r").read(),
adding_headers={"Content-Type": "application/json"},
status=200,
)

runner = CliRunner()
args = [
"deploy",
"manifest",
get_manifest_path("shinyapp"),
"--account",
"some-account",
"--token",
"someToken",
"--secret",
"c29tZVNlY3JldAo=",
"--title",
"myApp",
"--visibility",
"private",
"--app-id",
"8442",
]
try:
result = runner.invoke(cli, args)
assert result.exit_code == 0, result.output
finally:
if original_api_key_value:
os.environ["CONNECT_API_KEY"] = original_api_key_value
if original_server_value:
os.environ["CONNECT_SERVER"] = original_server_value


@httpretty.activate(verbose=True, allow_net_connect=False)
@pytest.mark.parametrize(
"project_application_id,project_id",
Expand Down