Skip to content

Commit

Permalink
feat: exclude applying changes that require resolving of secrets; mak…
Browse files Browse the repository at this point in the history
…e applying of changes fail-safe
  • Loading branch information
netomi committed Jan 29, 2024
1 parent 728d2c1 commit 9fcf475
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 12 deletions.
8 changes: 8 additions & 0 deletions otterdog/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ def of_changes(
async def apply(self, org_id: str, provider: GitHubProvider) -> None:
await self.fn(self, org_id, provider)

def __repr__(self) -> str:
obj = self.expected_object if self.expected_object is not None else self.current_object
assert obj is not None
return f"{self.patch_type.name} - {obj.get_model_header(self.parent_object)}"


@dataclasses.dataclass
class PatchContext(object):
Expand Down Expand Up @@ -426,6 +431,9 @@ def to_model_dict(self, for_diff: bool = False, include_nested_models: bool = Fa

return result

def contains_secrets(self) -> bool:
return False

def resolve_secrets(self, secret_resolver: Callable[[str], str]) -> None:
pass

Expand Down
3 changes: 3 additions & 0 deletions otterdog/models/secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ async def get_mapping_to_provider(
field.name: S(field.name) for field in cls.provider_fields() if not is_unset(data.get(field.name, UNSET))
}

def contains_secrets(self) -> bool:
return True

def resolve_secrets(self, secret_resolver: Callable[[str], str]) -> None:
secret_value = self.value
if not is_unset(secret_value) and secret_value is not None:
Expand Down
3 changes: 3 additions & 0 deletions otterdog/models/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ async def get_mapping_to_provider(

return mapping

def contains_secrets(self) -> bool:
return self.secret is not None

def resolve_secrets(self, secret_resolver: Callable[[str], str]) -> None:
webhook_secret = self.secret
if not is_unset(webhook_secret) and webhook_secret is not None:
Expand Down
13 changes: 12 additions & 1 deletion otterdog/operations/apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ def __init__(
update_filter: str,
delete_resources: bool,
resolve_secrets: bool = True,
include_resources_with_secrets: bool = True,
):
super().__init__(no_web_ui, update_webhooks, update_secrets, update_filter)
self._force_processing = force_processing
self._delete_resources = delete_resources
self._resolve_secrets = resolve_secrets
self._include_resources_with_secrets = include_resources_with_secrets

def init(self, config: OtterdogConfig, printer: IndentingPrinter) -> None:
super().init(config, printer)
Expand All @@ -40,6 +42,9 @@ def pre_execute(self) -> None:
self.printer.println("Applying changes:")
self.print_legend()

def include_resources_with_secrets(self) -> bool:
return self._include_resources_with_secrets

def resolve_secrets(self) -> bool:
return self._resolve_secrets

Expand Down Expand Up @@ -112,10 +117,16 @@ async def handle_finish(self, org_id: str, diff_status: DiffStatus, patches: lis
if patch.patch_type == LivePatchType.REMOVE and not self._delete_resources:
continue
else:
await patch.apply(org_id, self.gh_client)
try:
await patch.apply(org_id, self.gh_client)
except RuntimeError as ex:
self.printer.println()
self.printer.print_error(f"failed to apply patch: {patch!r}\n{ex}")

delete_snippet = "deleted" if self._delete_resources else "live resources ignored"

self.printer.println("\nDone.")

self.printer.println(
f"\n{style('Executed plan', bright=True)}: {diff_status.additions} added, "
f"{diff_status.differences} changed, "
Expand Down
25 changes: 15 additions & 10 deletions otterdog/operations/diff_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def gh_client(self) -> GitHubProvider:
def verbose_output(self):
return True

def include_resources_with_secrets(self) -> bool:
return True

def resolve_secrets(self) -> bool:
return True

Expand Down Expand Up @@ -146,8 +149,9 @@ def handle(patch: LivePatch) -> None:
match patch.patch_type:
case LivePatchType.ADD:
assert patch.expected_object is not None
self.handle_add_object(github_id, patch.expected_object, patch.parent_object)
diff_status.additions += 1
if self.include_resources_with_secrets() or not patch.expected_object.contains_secrets():
self.handle_add_object(github_id, patch.expected_object, patch.parent_object)
diff_status.additions += 1

case LivePatchType.REMOVE:
assert patch.current_object is not None
Expand All @@ -159,14 +163,15 @@ def handle(patch: LivePatch) -> None:
assert patch.current_object is not None
assert patch.expected_object is not None

diff_status.differences += self.handle_modified_object(
github_id,
patch.changes,
False,
patch.current_object,
patch.expected_object,
patch.parent_object,
)
if self.include_resources_with_secrets() or not patch.expected_object.contains_secrets():
diff_status.differences += self.handle_modified_object(
github_id,
patch.changes,
False,
patch.current_object,
patch.expected_object,
patch.parent_object,
)

context = LivePatchContext(
github_id, self.update_webhooks, self.update_secrets, self.update_filter, expected_org.settings
Expand Down
2 changes: 1 addition & 1 deletion otterdog/webapp/tasks/apply_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ async def apply_changes(
update_filter="",
delete_resources=True,
resolve_secrets=False,
include_resources_with_secrets=False,
)
operation.init(otterdog_config, printer)

# TODO: we need to exclude any change that requires credentials or the web ui
await operation.execute(org_config)

text = output.getvalue()
Expand Down

0 comments on commit 9fcf475

Please sign in to comment.