Skip to content

Commit 3346edc

Browse files
authored
🐙 octavia-cli: make update logic clearer (#11386)
1 parent 966849c commit 3346edc

File tree

2 files changed

+102
-98
lines changed

2 files changed

+102
-98
lines changed

octavia-cli/octavia_cli/apply/commands.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44

55
from glob import glob
6-
from typing import List, Tuple
6+
from typing import List, Optional, Tuple
77

88
import airbyte_api_client
99
import click
@@ -63,25 +63,27 @@ def apply_single_resource(resource: BaseResource, force: bool) -> None:
6363
click.echo("\n".join(messages))
6464

6565

66-
def should_update_resource(force: bool, diff: str, local_file_changed: bool) -> Tuple[bool, str]:
66+
def should_update_resource(force: bool, user_validation: Optional[bool], local_file_changed: bool) -> Tuple[bool, str]:
6767
"""Function to decide if the resource needs an update or not.
6868
6969
Args:
7070
force (bool): Whether force mode is on.
71-
diff (str): The computed diff between local and remote for this resource.
71+
user_validation (bool): User validated the existing changes.
7272
local_file_changed (bool): Whether the local file describing the resource was modified.
7373
7474
Returns:
7575
Tuple[bool, str]: Boolean to know if resource should be updated and string describing the update reason.
7676
"""
7777
if force:
78-
should_update, update_reason = True, "🚨 - Running update because force mode is on."
79-
elif diff:
80-
should_update, update_reason = True, "✍️ - Running update because a diff was detected between local and remote resource."
81-
elif local_file_changed:
78+
should_update, update_reason = True, "🚨 - Running update because the force mode is activated."
79+
elif user_validation is True:
80+
should_update, update_reason = True, "🟢 - Running update because you validated the changes."
81+
elif user_validation is False:
82+
should_update, update_reason = False, "🔴 - Did not update because you refused the changes."
83+
elif user_validation is None and local_file_changed:
8284
should_update, update_reason = (
8385
True,
84-
"✍️ - Running update because a local file change was detected and a secret field might have been edited.",
86+
"🟡 - Running update because a local file change was detected and a secret field might have been edited.",
8587
)
8688
else:
8789
should_update, update_reason = False, "😴 - Did not update because no change detected."
@@ -135,11 +137,14 @@ def update_resource(resource: BaseResource, force: bool) -> List[str]:
135137
Returns:
136138
List[str]: Post update messages to display to standard output.
137139
"""
140+
output_messages = []
138141
diff = resource.get_diff_with_remote_resource()
139-
should_update, update_reason = should_update_resource(force, diff, resource.local_file_changed)
140-
output_messages = [update_reason]
142+
user_validation = None
141143
if not force and diff:
142-
should_update = prompt_for_diff_validation(resource.resource_name, diff)
144+
user_validation = prompt_for_diff_validation(resource.resource_name, diff)
145+
should_update, update_reason = should_update_resource(force, user_validation, resource.local_file_changed)
146+
click.echo(update_reason)
147+
143148
if should_update:
144149
updated_resource, state = resource.update()
145150
output_messages.append(

octavia-cli/unit_tests/test_apply/test_commands.py

+86-87
Original file line numberDiff line numberDiff line change
@@ -94,47 +94,74 @@ def test_apply_single_resource(patch_click, mocker, resource_was_created):
9494

9595

9696
@pytest.mark.parametrize(
97-
"diff,local_file_changed,force,expected_should_update,expected_update_reason",
97+
"force,user_validation,local_file_changed,expect_update,expected_reason",
9898
[
99-
(True, True, True, True, "🚨 - Running update because force mode is on."), # check if force has the top priority
100-
(True, False, True, True, "🚨 - Running update because force mode is on."), # check if force has the top priority
101-
(True, False, False, True, "🚨 - Running update because force mode is on."), # check if force has the top priority
102-
(True, True, False, True, "🚨 - Running update because force mode is on."), # check if force has the top priority
103-
(
99+
pytest.param(
100+
True, True, True, True, "🚨 - Running update because the force mode is activated.", id="1 - Check if force has the top priority."
101+
),
102+
pytest.param(
103+
True,
104104
False,
105105
True,
106106
True,
107+
"🚨 - Running update because the force mode is activated.",
108+
id="2 - Check if force has the top priority.",
109+
),
110+
pytest.param(
107111
True,
108-
"✍️ - Running update because a diff was detected between local and remote resource.",
109-
), # check if diff has priority of file changed
110-
(
111112
False,
112-
True,
113113
False,
114114
True,
115-
"✍️ - Running update because a diff was detected between local and remote resource.",
116-
), # check if diff has priority of file changed
117-
(
115+
"🚨 - Running update because the force mode is activated.",
116+
id="3 - Check if force has the top priority.",
117+
),
118+
pytest.param(
119+
True,
120+
True,
118121
False,
122+
True,
123+
"🚨 - Running update because the force mode is activated.",
124+
id="4 - Check if force has the top priority.",
125+
),
126+
pytest.param(
119127
False,
120128
True,
121129
True,
122-
"✍️ - Running update because a local file change was detected and a secret field might have been edited.",
123-
), # check if local_file_changed runs even if no diff found
124-
(
130+
True,
131+
"🟢 - Running update because you validated the changes.",
132+
id="Check if user validation has priority over local file change.",
133+
),
134+
pytest.param(
125135
False,
126136
False,
137+
True,
138+
False,
139+
"🔴 - Did not update because you refused the changes.",
140+
id="Check if user validation has priority over local file change.",
141+
),
142+
pytest.param(
143+
False,
144+
None,
145+
True,
146+
True,
147+
"🟡 - Running update because a local file change was detected and a secret field might have been edited.",
148+
id="Check if local_file_changed runs even if user validation is None.",
149+
),
150+
pytest.param(
151+
False,
152+
None,
127153
False,
128154
False,
129155
"😴 - Did not update because no change detected.",
130-
), # check if local_file_changed runs even if no diff found
156+
id="Check no update if no local change and user validation is None.",
157+
),
131158
],
132159
)
133-
def test_should_update_resource(patch_click, mocker, diff, local_file_changed, force, expected_should_update, expected_update_reason):
134-
should_update, update_reason = commands.should_update_resource(diff, local_file_changed, force)
135-
assert should_update == expected_should_update
160+
def test_should_update_resource(patch_click, mocker, force, user_validation, local_file_changed, expect_update, expected_reason):
161+
should_update, update_reason = commands.should_update_resource(force, user_validation, local_file_changed)
162+
assert should_update == expect_update
136163
assert update_reason == commands.click.style.return_value
137-
commands.click.style.assert_called_with(expected_update_reason, fg="green")
164+
commands.click.style.assert_called_with(expected_reason, fg="green")
138165

139166

140167
@pytest.mark.parametrize(
@@ -177,80 +204,52 @@ def test_create_resource(patch_click, mocker):
177204

178205

179206
@pytest.mark.parametrize(
180-
"force,diff,should_update_resource,expect_prompt,user_validate_diff,expect_update,expected_number_of_messages",
207+
"force,diff,local_file_changed,expect_prompt,user_validation,expect_update",
181208
[
182-
(True, True, True, False, False, True, 3), # Force is on, we have a diff, prompt should not be displayed: we expect update.
183-
(
184-
True,
185-
False,
186-
True,
187-
False,
188-
False,
189-
True,
190-
3,
191-
), # Force is on, no diff, should_update_resource == true, prompt should not be displayed, we expect update.
192-
(
193-
True,
194-
False,
195-
False,
196-
False,
197-
False,
198-
False,
199-
1,
200-
), # Force is on, no diff, should_update_resource == false, prompt should not be displayed, we don't expect update. This scenario should not exists in current implementation as force always trigger update.
201-
(
202-
False,
203-
True,
204-
True,
205-
True,
206-
True,
207-
True,
208-
3,
209-
), # Force is off, we have diff, prompt should be displayed, user validate diff: we expected update.
210-
(
211-
False,
212-
False,
213-
True,
214-
False,
215-
False,
216-
True,
217-
3,
218-
), # Force is off, no diff, should_update_resource == true (in case of file change), prompt should not be displayed, we expect update.
219-
(
220-
False,
221-
True,
222-
True,
223-
True,
224-
False,
225-
False,
226-
1,
227-
), # Force is off, we have a diff but the user does not validate it: we don't expect update.
228-
(
229-
False,
230-
False,
231-
False,
232-
False,
233-
False,
234-
False,
235-
1,
236-
), # Force is off, we have a no diff, should_update_resource == false: we don't expect update.
209+
pytest.param(True, True, True, False, False, True, id="Force, diff, local file change -> no prompt, no validation, expect update."),
210+
pytest.param(
211+
True, True, False, False, False, True, id="Force, diff, no local file change -> no prompt, no validation, expect update."
212+
),
213+
pytest.param(
214+
True, False, False, False, False, True, id="Force, no diff, no local file change -> no prompt, no validation, expect update."
215+
),
216+
pytest.param(
217+
True, False, True, False, False, True, id="Force, no diff, local file change -> no prompt, no validation, expect update."
218+
),
219+
pytest.param(
220+
False, True, True, True, True, True, id="No force, diff, local file change -> expect prompt, validation, expect update."
221+
),
222+
pytest.param(
223+
False, True, True, True, False, False, id="No force, diff, local file change -> expect prompt, no validation, no update."
224+
),
225+
pytest.param(
226+
False, True, False, True, True, True, id="No force, diff, no local file change -> expect prompt, validation, expect update."
227+
),
228+
pytest.param(
229+
False, True, False, True, False, False, id="No force, diff, no local file change -> expect prompt, no validation, no update."
230+
),
231+
pytest.param(
232+
False, False, True, False, False, True, id="No force, no diff, local file change -> no prompt, no validation, expect update."
233+
),
234+
pytest.param(
235+
False, False, False, False, False, False, id="No force, no diff, no local file change -> no prompt, no validation, no update."
236+
),
237237
],
238238
)
239-
def test_update_resource(
240-
patch_click, mocker, force, diff, should_update_resource, user_validate_diff, expect_prompt, expect_update, expected_number_of_messages
241-
):
239+
def test_update_resource(patch_click, mocker, force, diff, local_file_changed, expect_prompt, user_validation, expect_update):
242240
mock_updated_resource = mocker.Mock()
243241
mock_state = mocker.Mock()
244242
mock_resource = mocker.Mock(
245243
get_diff_with_remote_resource=mocker.Mock(return_value=diff),
246244
resource_name="my_resource",
245+
local_file_changed=local_file_changed,
247246
update=mocker.Mock(return_value=(mock_updated_resource, mock_state)),
248247
)
249-
update_reason = "foo"
250-
mocker.patch.object(commands, "should_update_resource", mocker.Mock(return_value=(should_update_resource, update_reason)))
251-
mocker.patch.object(commands, "prompt_for_diff_validation", mocker.Mock(return_value=user_validate_diff))
248+
mocker.patch.object(commands, "prompt_for_diff_validation", mocker.Mock(return_value=user_validation))
252249

253250
output_messages = commands.update_resource(mock_resource, force)
251+
commands.click.echo.assert_called_once()
252+
254253
if expect_prompt:
255254
commands.prompt_for_diff_validation.assert_called_once_with("my_resource", diff)
256255
else:
@@ -259,11 +258,9 @@ def test_update_resource(
259258
mock_resource.update.assert_called_once()
260259
else:
261260
mock_resource.update.assert_not_called()
262-
assert output_messages[0] == commands.should_update_resource.return_value[1] == update_reason
263-
assert len(output_messages) == expected_number_of_messages
264-
if expected_number_of_messages == 3:
261+
262+
if expect_update:
265263
assert output_messages == [
266-
commands.should_update_resource.return_value[1],
267264
commands.click.style.return_value,
268265
commands.click.style.return_value,
269266
]
@@ -273,6 +270,8 @@ def test_update_resource(
273270
mocker.call(f"💾 - New state for {mock_updated_resource.name} stored at {mock_state.path}.", fg="yellow"),
274271
]
275272
)
273+
else:
274+
assert output_messages == []
276275

277276

278277
def test_find_local_configuration_files(mocker):

0 commit comments

Comments
 (0)