Skip to content

Commit 8d15066

Browse files
authored
Merge pull request #74 from DataKitchen/volume-owner
fix: attempt to set volume owner on tg upgrade
2 parents 06ae7b9 + 4b13011 commit 8d15066

3 files changed

Lines changed: 78 additions & 24 deletions

File tree

dk-installer.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@
7777
TESTGEN_PULL_TIMEOUT = 5
7878
TESTGEN_PULL_RETRIES = 3
7979
TESTGEN_DEFAULT_PORT = 8501
80-
TESTGEN_LATEST_VERSIONS_URL = "https://dk-support-external.s3.us-east-1.amazonaws.com/testgen-observability/testgen-latest-versions.json"
80+
TESTGEN_LATEST_VERSIONS_URL = (
81+
"https://dk-support-external.s3.us-east-1.amazonaws.com/testgen-observability/testgen-latest-versions.json"
82+
)
8183

8284
MIXPANEL_TOKEN = "4eff51580bc1685b8ffe79ffb22d2704"
8385
MIXPANEL_URL = "https://api.mixpanel.com"
@@ -1636,7 +1638,7 @@ class UpdateComposeFileStep(Step):
16361638
label = "Updating the Docker compose file"
16371639

16381640
def __init__(self):
1639-
self.update_version = None
1641+
self.update_version = False
16401642
self.update_analytics = False
16411643
self.update_token = False
16421644
super().__init__()
@@ -1647,7 +1649,9 @@ def pre_execute(self, action, args):
16471649
CONSOLE.space()
16481650

16491651
contents = action.docker_compose_file_path.read_text()
1650-
if not args.skip_verify:
1652+
if args.skip_verify:
1653+
self.update_version = True
1654+
else:
16511655
try:
16521656
output = action.run_cmd(
16531657
"docker",
@@ -1660,30 +1664,30 @@ def pre_execute(self, action, args):
16601664
"--help",
16611665
capture_text=True,
16621666
)
1663-
version_match = re.search(r"TestGen\s([0-9.]*)", output)
1667+
version_match = re.search(r"TestGen\s(?:[a-zA-Z]+\s)*([0-9.]*)", output)
16641668
current_version = version_match.group(1)
16651669

16661670
image_match = re.search(r"image:\s*(datakitchen.+):.+\n", contents)
16671671
docker_image = image_match.group(1)
16681672
latest_version = "unknown"
1669-
1673+
16701674
ssl_context = ssl.create_default_context()
16711675
ssl_context.check_hostname = False
16721676
ssl_context.verify_mode = ssl.CERT_NONE
16731677
resp = urllib.request.urlopen(TESTGEN_LATEST_VERSIONS_URL, timeout=3, context=ssl_context)
16741678
if resp.code == 200:
1675-
json_data = json.loads(resp.read().decode('utf-8'))
1679+
json_data = json.loads(resp.read().decode("utf-8"))
16761680
latest_version = json_data.get("docker", {}).get(docker_image)
16771681
except Exception:
16781682
CONSOLE.msg("Current version: unknown")
16791683
CONSOLE.msg("Latest version: unknown")
1680-
pass
1684+
self.update_version = True
16811685
else:
16821686
CONSOLE.msg(f"Current version: {current_version}")
16831687
CONSOLE.msg(f"Latest version: {latest_version}")
16841688

16851689
if current_version != latest_version:
1686-
self.update_version = latest_version
1690+
self.update_version = True
16871691
else:
16881692
CONSOLE.msg("Application is already up-to-date.")
16891693

@@ -1983,6 +1987,30 @@ def execute(self, action, args):
19831987
)
19841988

19851989

1990+
class TestGenUpdateVolumeStep(Step):
1991+
label = "Updating docker volume"
1992+
1993+
def execute(self, action, args):
1994+
try:
1995+
# Set testgen user as volume owner in case UID changes
1996+
action.run_cmd(
1997+
"docker",
1998+
"compose",
1999+
"-f",
2000+
action.docker_compose_file_path,
2001+
"run",
2002+
"--entrypoint",
2003+
"/bin/sh -c",
2004+
"--user",
2005+
"root",
2006+
"--rm",
2007+
"engine",
2008+
"chown -R testgen:testgen /var/lib/testgen",
2009+
)
2010+
except CommandFailed:
2011+
raise SkipStep
2012+
2013+
19862014
class TestGenSetupDatabaseStep(Step):
19872015
label = "Initializing the platform database"
19882016

@@ -2034,7 +2062,7 @@ def on_action_success(self, action, args):
20342062
capture_text=True,
20352063
)
20362064

2037-
match = re.search("This version:(.*)", output)
2065+
match = re.search(r"TestGen\s(?:[a-zA-Z]+\s)*([0-9.]*)", output)
20382066
CONSOLE.msg(f"Application version: {match.group(1)}")
20392067

20402068

@@ -2119,6 +2147,7 @@ class TestgenUpgradeAction(TestgenActionMixin, AnalyticsMultiStepAction):
21192147
UpdateComposeFileStep,
21202148
TestGenStopStep,
21212149
TestGenPullImagesStep,
2150+
TestGenUpdateVolumeStep,
21222151
TestGenStartStep,
21232152
TestGenUpgradeDatabaseStep,
21242153
]

tests/conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ def stream_iter_mock():
7272
yield si_mock
7373

7474

75+
@pytest.fixture
76+
def version_check_mock():
77+
with patch("urllib.request.urlopen") as mock:
78+
yield mock
79+
80+
7581
@pytest.fixture
7682
def analytics_mock():
7783
with patch("tests.installer.AnalyticsWrapper") as mock:

tests/test_tg_upgrade.py

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import textwrap
23
from unittest.mock import call
34

@@ -18,14 +19,14 @@ def tg_upgrade_action(action_cls, args_mock, tmp_data_folder, start_cmd_mock, re
1819
def tg_upgrade_stdout_side_effect(stdout_mock):
1920
side_effect = [
2021
# Pre-execute calls
21-
[b"This version: 1.0.0\n", b"Latest version: 1.1.0\n"], # Version check
22+
[b"TestGen 1.0.0\n"], # Version check
2223
# Execute calls
2324
[], # Down
2425
[], # Pull
2526
[], # Up
2627
[], # Upgrade DB
2728
# Post-execute calls
28-
[b"This version: 1.1.0\n", b"Latest version: 1.1.0\n"], # Confirmation version check
29+
[b"TestGen 1.1.0\n"], # Confirmation version check
2930
[b"[]"], # Image data collection
3031
]
3132

@@ -57,9 +58,15 @@ def get_compose_content(*extra_vars):
5758
return template.format(textwrap.indent("\n".join(extra_vars), " "))
5859

5960

61+
def set_version_check_mock(version_check_mock, latest_version):
62+
version_check_mock.return_value.code = 200
63+
version_values = { "docker": {"datakitchen/dataops-testgen": latest_version } }
64+
version_check_mock.return_value.read.return_value = json.dumps(version_values).encode("utf-8")
65+
66+
6067
@pytest.mark.integration
6168
def test_tg_upgrade_compose_missing(tg_upgrade_action, args_mock, start_cmd_mock, console_msg_mock):
62-
start_cmd_mock.__exit__.side_effect = [None, None, None, CommandFailed]
69+
start_cmd_mock.__exit__.side_effect = [None, None, CommandFailed]
6370

6471
with pytest.raises(AbortAction, match=""):
6572
tg_upgrade_action._check_requirements(args_mock)
@@ -68,7 +75,22 @@ def test_tg_upgrade_compose_missing(tg_upgrade_action, args_mock, start_cmd_mock
6875

6976

7077
@pytest.mark.integration
71-
def test_tg_upgrade(tg_upgrade_action, compose_path, start_cmd_mock, tg_upgrade_stdout_side_effect, args_mock):
78+
@pytest.mark.parametrize(
79+
"skip_verify, latest_version",
80+
((True, "1.0.0"), (False, "1.1.0")),
81+
)
82+
def test_tg_upgrade(
83+
skip_verify,
84+
latest_version,
85+
tg_upgrade_action,
86+
compose_path,
87+
start_cmd_mock,
88+
tg_upgrade_stdout_side_effect,
89+
args_mock,
90+
version_check_mock,
91+
):
92+
args_mock.skip_verify = skip_verify
93+
set_version_check_mock(version_check_mock, latest_version)
7294
compose_path.write_text(get_compose_content())
7395

7496
tg_upgrade_action.execute(args_mock)
@@ -93,21 +115,16 @@ def test_tg_upgrade(tg_upgrade_action, compose_path, start_cmd_mock, tg_upgrade_
93115

94116

95117
@pytest.mark.integration
96-
@pytest.mark.parametrize(
97-
"skip_verify, latest_version",
98-
((True, b"1.0.0"), (True, b"1.1.0"), (False, b"1.0.0")),
99-
)
100118
def test_tg_upgrade_abort(
101-
skip_verify,
102-
latest_version,
103119
tg_upgrade_action,
104120
compose_path,
105121
start_cmd_mock,
106122
tg_upgrade_stdout_side_effect,
107123
args_mock,
124+
version_check_mock,
108125
):
109-
args_mock.skip_verify = skip_verify
110-
tg_upgrade_stdout_side_effect[0][1] = b"Latest version: %b\n" % latest_version
126+
args_mock.skip_verify = False
127+
set_version_check_mock(version_check_mock, "1.0.0")
111128
initial_compose_content = get_compose_content("TG_INSTANCE_ID: test-instance-id")
112129
compose_path.write_text(initial_compose_content)
113130

@@ -116,7 +133,7 @@ def test_tg_upgrade_abort(
116133

117134
compose_content = compose_path.read_text()
118135
assert compose_content == initial_compose_content
119-
assert start_cmd_mock.call_count == 0 if skip_verify else 1
136+
assert start_cmd_mock.call_count == 1
120137

121138

122139
@pytest.mark.integration
@@ -130,8 +147,9 @@ def test_tg_upgrade_enable_analytics(
130147
args_mock,
131148
console_msg_mock,
132149
analytics_mock,
150+
version_check_mock,
133151
):
134-
tg_upgrade_stdout_side_effect[0][1] = b"Latest version: 1.0.0\n"
152+
set_version_check_mock(version_check_mock, "1.0.0")
135153
compose_path.write_text(get_compose_content("TG_ANALYTICS: no" if re_enable else ""))
136154
analytics_mock.get_instance_id.return_value = "test-instance-id"
137155

@@ -153,9 +171,10 @@ def test_tg_upgrade_disable_analytics(
153171
tg_upgrade_stdout_side_effect,
154172
args_mock,
155173
console_msg_mock,
174+
version_check_mock,
156175
):
157176
args_mock.send_analytics_data = False
158-
tg_upgrade_stdout_side_effect[0][1] = b"Latest version: 1.0.0\n"
177+
set_version_check_mock(version_check_mock, "1.0.0")
159178
compose_path.write_text(
160179
get_compose_content("TG_INSTANCE_ID: test-instance-id", "TG_ANALYTICS: yes" if explicitly_enabled else "")
161180
)

0 commit comments

Comments
 (0)