Skip to content

Commit 1499cdc

Browse files
committed
Update content build retry test, update test setup
1 parent 01c561c commit 1499cdc

File tree

2 files changed

+114
-61
lines changed

2 files changed

+114
-61
lines changed

tests/test_main_content.py

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,55 +15,63 @@
1515

1616
from .utils import apply_common_args
1717

18-
_bundle_download_dest = "download.tar.gz"
19-
_test_build_dir = "rsconnect-build-test"
18+
# These tests need to run in order because they share the same tempdir
19+
# For some reason setup and teardown aren't enough to fully reset the state
20+
# between tests. Overriding the env var CONNECT_CONTENT_BUILD_DIR to be a tempdir
21+
# would be preferable but this is fine for now.
22+
TEMP_DIR="rsconnect-build-test"
2023

2124
def register_uris(connect_server: str):
25+
def register_content_endpoints(i: int, guid: str):
26+
httpretty.register_uri(
27+
httpretty.GET,
28+
f"{connect_server}/__api__/v1/content/{guid}",
29+
body=open(f"tests/testdata/connect-responses/describe-content-{i}.json", "r").read(),
30+
adding_headers={"Content-Type": "application/json"},
31+
)
32+
httpretty.register_uri(
33+
httpretty.POST,
34+
f"{connect_server}/__api__/v1/content/{guid}/build",
35+
body='{"task_id": "1234"}',
36+
adding_headers={"Content-Type": "application/json"},
37+
)
38+
httpretty.register_uri(
39+
httpretty.GET,
40+
f"{connect_server}/__api__/applications/{guid}/config",
41+
body='{' +
42+
f'"config_url": "{connect_server}/connect/#/apps/{guid}",' +
43+
f'"logs_url": "{connect_server}/connect/#/apps/{guid}"' +
44+
'}',
45+
adding_headers={"Content-Type": "application/json"},
46+
)
47+
2248
httpretty.register_uri(
2349
httpretty.GET,
24-
f"%s/__api__/server_settings" % (connect_server),
50+
f"{connect_server}/__api__/server_settings",
2551
body=open("tests/testdata/connect-responses/server_settings.json", "r").read(),
2652
adding_headers={"Content-Type": "application/json"},
2753
)
2854
httpretty.register_uri(
2955
httpretty.GET,
30-
f"%s/__api__/me" % (connect_server),
56+
f"{connect_server}/__api__/me",
3157
body=open("tests/testdata/connect-responses/me.json", "r").read(),
3258
adding_headers={"Content-Type": "application/json"},
3359
)
3460
httpretty.register_uri(
3561
httpretty.GET,
36-
f"%s/__api__/v1/content" % (connect_server),
62+
f"{connect_server}/__api__/v1/content",
3763
body=open("tests/testdata/connect-responses/list-content.json", "r").read(),
3864
adding_headers={"Content-Type": "application/json"},
3965
)
4066
httpretty.register_uri(
4167
httpretty.GET,
42-
f"%s/__api__/v1/content/7d59c5c7-c4a7-4950-acc3-3943b7192bc4" % (connect_server),
43-
body=open("tests/testdata/connect-responses/describe-content-1.json", "r").read(),
44-
adding_headers={"Content-Type": "application/json"},
45-
)
46-
httpretty.register_uri(
47-
httpretty.GET,
48-
f"%s/__api__/v1/content/ab497e4b-b706-4ae7-be49-228979a95eb4" % (connect_server),
49-
body=open("tests/testdata/connect-responses/describe-content-2.json", "r").read(),
50-
adding_headers={"Content-Type": "application/json"},
51-
)
52-
httpretty.register_uri(
53-
httpretty.GET,
54-
f"%s/__api__/v1/content/7d59c5c7-c4a7-4950-acc3-3943b7192bc4/bundles/92/download" % (connect_server),
68+
f"{connect_server}/__api__/v1/content/7d59c5c7-c4a7-4950-acc3-3943b7192bc4/bundles/92/download",
5569
body=open("tests/testdata/bundle.tar.gz", "rb").read(),
5670
adding_headers={"Content-Type": "application/tar+gzip"},
5771
)
58-
httpretty.register_uri(
59-
httpretty.POST,
60-
f"%s/__api__/v1/content/7d59c5c7-c4a7-4950-acc3-3943b7192bc4/build" % (connect_server),
61-
body='{"task_id": "1234"}',
62-
adding_headers={"Content-Type": "application/json"},
63-
)
6472
httpretty.register_uri(
6573
httpretty.GET,
66-
f"%s/__api__/tasks/1234" % (connect_server),
74+
f"{connect_server}/__api__/tasks/1234",
6775
body="""{
6876
"id": "1234",
6977
"user_id": 0,
@@ -76,23 +84,15 @@ def register_uris(connect_server: str):
7684
}""",
7785
adding_headers={"Content-Type": "application/json"},
7886
)
79-
httpretty.register_uri(
80-
httpretty.GET,
81-
f"%s/__api__/applications/7d59c5c7-c4a7-4950-acc3-3943b7192bc4/config" % (connect_server),
82-
body="""{
83-
"config_url": "http://localhost:3939/connect/#/apps/7d59c5c7-c4a7-4950-acc3-3943b7192bc4",
84-
"logs_url": "http://localhost:3939/connect/#/apps/7d59c5c7-c4a7-4950-acc3-3943b7192bc4/logs"
85-
}""",
86-
adding_headers={"Content-Type": "application/json"},
87-
)
87+
register_content_endpoints(1, "7d59c5c7-c4a7-4950-acc3-3943b7192bc4")
88+
register_content_endpoints(2, "ab497e4b-b706-4ae7-be49-228979a95eb4")
89+
register_content_endpoints(3, "cdfed1f7-0e09-40eb-996d-0ef77ea2d797")
8890

8991
class TestContentSubcommand(unittest.TestCase):
9092
@classmethod
9193
def tearDownClass(cls):
92-
if os.path.exists(_bundle_download_dest):
93-
os.remove(_bundle_download_dest)
94-
if os.path.exists(_test_build_dir):
95-
shutil.rmtree(_test_build_dir, ignore_errors=True)
94+
if os.path.exists(TEMP_DIR):
95+
shutil.rmtree(TEMP_DIR, ignore_errors=True)
9696

9797
def setUp(self):
9898
self.connect_server = "http://localhost:3939"
@@ -138,11 +138,11 @@ def test_content_download_bundle(self):
138138
runner = CliRunner()
139139
args = ["content", "download-bundle",
140140
"-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4",
141-
"-o", _bundle_download_dest]
141+
"-o", f"{TEMP_DIR}/bundle.tar.gz"]
142142
apply_common_args(args, server=self.connect_server, key=self.api_key)
143143
result = runner.invoke(cli, args)
144144
self.assertEqual(result.exit_code, 0, result.output)
145-
with tarfile.open(_bundle_download_dest, mode="r:gz") as tgz:
145+
with tarfile.open(f"{TEMP_DIR}/bundle.tar.gz", mode="r:gz") as tgz:
146146
manifest = json.loads(tgz.extractfile("manifest.json").read())
147147
self.assertIn("metadata", manifest)
148148

@@ -157,7 +157,7 @@ def test_build(self):
157157
result = runner.invoke(cli, args)
158158
self.assertEqual(result.exit_code, 0, result.output)
159159
self.assertTrue(
160-
os.path.exists("%s/%s.json" % (_test_build_dir, _normalize_server_url(self.connect_server)))
160+
os.path.exists("%s/%s.json" % (TEMP_DIR, _normalize_server_url(self.connect_server)))
161161
)
162162

163163
# list the "tracked" content
@@ -186,34 +186,28 @@ def test_build(self):
186186
self.assertTrue(len(listing) == 1)
187187
self.assertEqual(listing[0]["rsconnect_build_status"], BuildStatus.COMPLETE)
188188

189+
@httpretty.activate(verbose=True, allow_net_connect=False)
189190
def test_build_retry(self):
190191
register_uris(self.connect_server)
191192
runner = CliRunner()
192193

193-
# add a content item
194-
args = ["content", "build", "add", "-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4"]
194+
# add 3 content items
195+
args = ["content", "build", "add",
196+
"-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4",
197+
"-g", "ab497e4b-b706-4ae7-be49-228979a95eb4",
198+
"-g", "cdfed1f7-0e09-40eb-996d-0ef77ea2d797"]
195199
apply_common_args(args, server=self.connect_server, key=self.api_key)
196200
result = runner.invoke(cli, args)
197201
self.assertEqual(result.exit_code, 0, result.output)
198202
self.assertTrue(
199-
os.path.exists("%s/%s.json" % (_test_build_dir, _normalize_server_url(self.connect_server)))
203+
os.path.exists("%s/%s.json" % (TEMP_DIR, _normalize_server_url(self.connect_server)))
200204
)
201205

202-
# list the "tracked" content
203-
args = ["content", "build", "ls", "-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4"]
204-
apply_common_args(args, server=self.connect_server, key=self.api_key)
205-
result = runner.invoke(cli, args)
206-
self.assertEqual(result.exit_code, 0, result.output)
207-
listing = json.loads(result.output)
208-
self.assertTrue(len(listing) == 1)
209-
self.assertEqual(listing[0]["guid"], "7d59c5c7-c4a7-4950-acc3-3943b7192bc4")
210-
self.assertEqual(listing[0]["bundle_id"], "92")
211-
self.assertEqual(listing[0]["rsconnect_build_status"], BuildStatus.NEEDS_BUILD)
212-
213-
# set the content build status to RUNNING so it looks like it was interrupted
214-
# and the cleanup did not have time to finish, otherwise it would be marked as ABORTED
206+
# change the content build status so it looks like it was interrupted/failed
215207
store = ContentBuildStore(RSConnectServer(self.connect_server, self.api_key))
216208
store.set_content_item_build_status("7d59c5c7-c4a7-4950-acc3-3943b7192bc4", BuildStatus.RUNNING)
209+
store.set_content_item_build_status("ab497e4b-b706-4ae7-be49-228979a95eb4", BuildStatus.ABORTED)
210+
store.set_content_item_build_status("cdfed1f7-0e09-40eb-996d-0ef77ea2d797", BuildStatus.ERROR)
217211

218212
# run the build
219213
args = ["content", "build", "run", "--retry"]
@@ -222,25 +216,39 @@ def test_build_retry(self):
222216
self.assertEqual(result.exit_code, 0, result.output)
223217

224218
# check that the build succeeded
225-
args = ["content", "build", "ls", "-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4"]
219+
args = ["content", "build", "ls",
220+
"-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4",
221+
"-g", "ab497e4b-b706-4ae7-be49-228979a95eb4",
222+
"-g", "cdfed1f7-0e09-40eb-996d-0ef77ea2d797"]
226223
apply_common_args(args, server=self.connect_server, key=self.api_key)
227224
result = runner.invoke(cli, args)
228225
self.assertEqual(result.exit_code, 0, result.output)
229226
listing = json.loads(result.output)
230-
self.assertTrue(len(listing) == 1)
227+
self.assertTrue(len(listing) == 3)
231228
self.assertEqual(listing[0]["rsconnect_build_status"], BuildStatus.COMPLETE)
229+
self.assertEqual(listing[1]["rsconnect_build_status"], BuildStatus.COMPLETE)
230+
self.assertEqual(listing[2]["rsconnect_build_status"], BuildStatus.COMPLETE)
232231

232+
@httpretty.activate(verbose=True, allow_net_connect=False)
233233
def test_build_rm(self):
234234
register_uris(self.connect_server)
235235
runner = CliRunner()
236236

237-
# remove a content item
237+
# remove all the content items
238238
args = ["content", "build", "rm", "-g", "7d59c5c7-c4a7-4950-acc3-3943b7192bc4"]
239239
apply_common_args(args, server=self.connect_server, key=self.api_key)
240240
result = runner.invoke(cli, args)
241241
self.assertEqual(result.exit_code, 0, result.output)
242+
args = ["content", "build", "rm", "-g", "ab497e4b-b706-4ae7-be49-228979a95eb4"]
243+
apply_common_args(args, server=self.connect_server, key=self.api_key)
244+
result = runner.invoke(cli, args)
245+
self.assertEqual(result.exit_code, 0, result.output)
246+
args = ["content", "build", "rm", "-g", "cdfed1f7-0e09-40eb-996d-0ef77ea2d797"]
247+
apply_common_args(args, server=self.connect_server, key=self.api_key)
248+
result = runner.invoke(cli, args)
249+
self.assertEqual(result.exit_code, 0, result.output)
242250

243-
# check that it was removed
251+
# check that they were removed
244252
args = ["content", "build", "ls"]
245253
apply_common_args(args, server=self.connect_server, key=self.api_key)
246254
result = runner.invoke(cli, args)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"guid": "cdfed1f7-0e09-40eb-996d-0ef77ea2d797",
3+
"name": "plumbr-testing",
4+
"title": "plumbr-testing",
5+
"description": "",
6+
"access_type": "acl",
7+
"connection_timeout": null,
8+
"read_timeout": null,
9+
"init_timeout": null,
10+
"idle_timeout": null,
11+
"max_processes": null,
12+
"min_processes": null,
13+
"max_conns_per_process": null,
14+
"load_factor": null,
15+
"memory_request": null,
16+
"memory_limit": null,
17+
"cpu_request": null,
18+
"cpu_limit": null,
19+
"amd_gpu_limit": null,
20+
"nvidia_gpu_limit": null,
21+
"service_account_name": null,
22+
"default_image_name": null,
23+
"created_time": "2023-09-11T18:32:48Z",
24+
"last_deployed_time": "2023-09-11T18:32:50Z",
25+
"bundle_id": "17",
26+
"app_mode": "api",
27+
"content_category": "api",
28+
"parameterized": false,
29+
"cluster_name": "Local",
30+
"image_name": null,
31+
"r_version": "4.3.0",
32+
"py_version": null,
33+
"quarto_version": null,
34+
"r_environment_management": true,
35+
"default_r_environment_management": null,
36+
"py_environment_management": null,
37+
"default_py_environment_management": null,
38+
"run_as": null,
39+
"run_as_current_user": false,
40+
"owner_guid": "820f092f-d564-4ab5-819a-0f4d2f03d11e",
41+
"content_url": "http://localhost:3939/content/cdfed1f7-0e09-40eb-996d-0ef77ea2d797/",
42+
"dashboard_url": "http://localhost:3939/connect/#/apps/cdfed1f7-0e09-40eb-996d-0ef77ea2d797",
43+
"app_role": "owner",
44+
"id": "12"
45+
}

0 commit comments

Comments
 (0)