Skip to content

feat(apps): add list and patch#1344

Open
wesjdj wants to merge 28 commits into
add-apps-featurefrom
add-apps-list-patch
Open

feat(apps): add list and patch#1344
wesjdj wants to merge 28 commits into
add-apps-featurefrom
add-apps-list-patch

Conversation

@wesjdj

@wesjdj wesjdj commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

/deploy renku=add-apps-beta extra-values=apps.enabled=true

@wesjdj wesjdj requested review from a team, SalimKayal and sgaist as code owners June 5, 2026 15:23
@wesjdj wesjdj marked this pull request as draft June 5, 2026 15:24
@wesjdj wesjdj changed the base branch from main to add-apps-delete June 5, 2026 15:29
@coveralls

coveralls commented Jun 5, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 27267062499

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Warning

No base build found for commit ea0d84d on add-apps-delete.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 86.133%

Details

  • Patch coverage: 68 uncovered changes across 4 files (49 of 117 lines covered, 41.88%).

Uncovered Changes

File Changed Covered %
components/renku_data_services/renku_apps/repository.py 31 4 12.9%
components/renku_data_services/renku_apps/k8s_client.py 36 13 36.11%
components/renku_data_services/renku_apps/blueprints.py 16 2 12.5%
components/renku_data_services/renku_apps/core.py 5 1 20.0%
Total (7 files) 117 49 41.88%

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 31953
Covered Lines: 27522
Line Coverage: 86.13%
Coverage Strength: 1.5 hits per line

💛 - Coveralls

@RenkuBot

RenkuBot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

You can access the deployment of this PR at https://renku-ci-ds-1344.dev.renku.ch

@wesjdj wesjdj changed the title add apps list patch feat(apps): add list and patch Jun 8, 2026
@wesjdj wesjdj marked this pull request as ready for review June 16, 2026 09:11
) -> JSONResponse:
project_id = ULID.from_str(query.project_id) if query.project_id is not None else None
apps = await self.apps_repo.list_apps(user=user, project_id=project_id)
return json([app.as_apispec().model_dump(exclude_none=True, mode="json") for app in apps])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry I missed this in the first review. But you can use validate_and_dump here. This is from renku_data_services.base_models.validation. For example see how get_all for data connector does this.

Comment on lines +108 to +118
raise errors.MissingResourceError(
message=f"App with name '{app_name}' does not exist or you do not have access to it."
)

launcher = await self.session_repo.get_launcher(user, runtime_state.launcher_id)

authorized = await self.authz.has_permission(user, ResourceType.project, launcher.project_id, Scope.WRITE)
if not authorized:
raise errors.MissingResourceError(
message=f"App with name '{app_name}' does not exist or you do not have authorization to modify it."
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: make the two error messages the same so people cannot tell how far they got and what does or does not exist in case they do not have access.

Comment on lines +128 to +146
async def set_app_deployment_resources(self, app_name: str, resource_class: ResourceClass) -> AppRuntimeState:
"""Update the container resources of the app to match the given resource class."""
cluster = await self.__client.cluster_by_id(self.__cluster_id)
meta = K8sObjectMeta(
name=app_name,
namespace=cluster.namespace,
cluster=cluster.id,
gvk=KNATIVE_SERVICE_GVK,
user_id=DUMMY_RENKU_APP_USER_ID,
)
patch_body: list[dict[str, Any]] = [
{
"op": "replace",
"path": "/spec/template/spec/containers/0/resources",
"value": _resources_from_resource_class(resource_class),
}
]
updated = await self.__client.patch(meta, patch_body)
return _extract_runtime_state(KnativeService.model_validate(updated.manifest))

@olevski olevski Jun 16, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking): It is better to use a strategic merge patch because it will not depend on the position of the container but would match on the container name. Which is more robust. One slight setback with a strategic merge patch is that it will update only unless you set the field to None. So if you have fields that are not set in the required/final state you should not exclude them but set them to None.

We can just take this as a future improvement though. And we just add a TODO comment here or open an issue. This will only be a problem once we add more than 1 container.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked in the code and the patching in the k8s client we used to wrap kr8s is either json or merge patch. It does not have a way to make it a strategic merge patch. So lets just add a TODO comment or open an issue. Our wrapper around the kr8s library just guesses the patch type and it never guesses strategic merge patch.

Comment on lines +124 to +127
if state == apispec.AppState.hibernated:
latest = await self.k8s_client.hibernate_app_deployment(app_name)
elif state == apispec.AppState.running:
latest = await self.k8s_client.resume_app_deployment(app_name)

@olevski olevski Jun 16, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick(non-blocking): You could potentially save some api calls here and patch only if the current state does not match the desired state. Doing the same for the resource class is a bit too scary and the resource class could have been updated and it has new values that should be updated.

Comment on lines +120 to +123
latest: AppRuntimeState = runtime_state
if resource_class_id is not None:
resource_class = await self.rp_repo.get_resource_class(user, resource_class_id)
latest = await self.k8s_client.set_app_deployment_resources(app_name, resource_class)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you are going from hibernated to running you should pull the resource class and update it. Even if the resource class id is the same the definition of the resource class may have changed and in this case we should also update the resources.

Base automatically changed from add-apps-delete to add-apps-feature June 18, 2026 09:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants