Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[backups][WIP] Draft Job strategy implementation#1721

Draft
lllamnyp wants to merge 1 commit intomaincozystack/cozystack:mainfrom
feat/jobdriver-implementationcozystack/cozystack:feat/jobdriver-implementationCopy head branch name to clipboard
Draft

[backups][WIP] Draft Job strategy implementation#1721
lllamnyp wants to merge 1 commit intomaincozystack/cozystack:mainfrom
feat/jobdriver-implementationcozystack/cozystack:feat/jobdriver-implementationCopy head branch name to clipboard

Conversation

@lllamnyp
Copy link
Member

TODO

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/jobdriver-implementation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @lllamnyp, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request lays the foundational groundwork for a robust backup system by implementing the BackupJobStrategyReconciler. This controller intelligently interprets BackupJob resources, dynamically retrieves related application and strategy definitions, and then leverages a newly introduced generic templating engine to construct and deploy Kubernetes batch/v1.Job resources. This design ensures a highly configurable and adaptable approach to managing application backups within the Kubernetes ecosystem.

Highlights

  • BackupJob Strategy Reconciler: Introduced the initial implementation of the BackupJobStrategyReconciler which processes BackupJob custom resources. This reconciler is responsible for orchestrating backup operations based on defined strategies.
  • Dynamic Resource Fetching: The reconciler now dynamically fetches associated application and strategy resources using Kubernetes' dynamic client and REST mapper, allowing for flexible interaction with various custom resource definitions.
  • Generic Templating Utility: A new generic templating utility has been added, enabling the dynamic population of fields within Kubernetes object specifications. This is crucial for creating flexible and configurable backup jobs.
  • Kubernetes Job Creation: The controller now creates Kubernetes batch/v1.Job resources. These jobs are constructed using a templated PodTemplateSpec derived from the JobStrategy object, allowing for customized backup execution.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new JobStrategy implementation for BackupJob resources, allowing the creation of Kubernetes Jobs based on templated PodTemplateSpec definitions. It also includes a generic templating utility to process Go template expressions within Kubernetes objects. The changes are a good step towards a flexible backup strategy. However, there are a few areas that could be improved for robustness and error handling, particularly regarding the templating logic and handling of API group references.

Comment on lines +19 to +25
templateFunc := func(in string) string {
out, err := template(in, templateContext)
if err != nil {
return in
}
return out
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The templateFunc silently swallows errors from template(in, templateContext), returning the original string in instead. This can lead to subtle bugs where template expressions are malformed or refer to non-existent fields, but no error is propagated, and the resulting object contains untemplated strings. It would be more robust to propagate these errors or at least log them with a higher severity to make debugging easier.

Suggested change
templateFunc := func(in string) string {
out, err := template(in, templateContext)
if err != nil {
return in
}
return out
}
templateFunc := func(in string) string {
out, err := template(in, templateContext)
if err != nil {
// TODO: Log this error or return it from Template function for better error visibility
return in
}
return out
}

Comment on lines +56 to +64
if j.Spec.ApplicationRef.APIGroup != nil {
applicationRefAPIGroup = *j.Spec.ApplicationRef.APIGroup
}
if j.Spec.StrategyRef.APIGroup != nil {
strategyRefAPIGroup = *j.Spec.StrategyRef.APIGroup
}
if j.Spec.StorageRef.APIGroup != nil {
storageRefAPIGroup = *j.Spec.StorageRef.APIGroup
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The APIGroup fields in TypedLocalObjectReference are pointers to strings. If they are nil, the current logic initializes applicationRefAPIGroup, strategyRefAPIGroup, and storageRefAPIGroup to empty strings. While an empty string for APIGroup typically refers to the core Kubernetes API group, this behavior is implicit and not explicitly handled or documented. It might be clearer to explicitly check for nil and assign "" if that's the intended behavior for core API group resources, or handle it as an error if APIGroup is always expected to be set for non-core resources.

var applicationRefAPIGroup string
var strategyRefAPIGroup string
var storageRefAPIGroup string
if j.Spec.ApplicationRef.APIGroup != nil {
	applicationRefAPIGroup = *j.Spec.ApplicationRef.APIGroup
} else {
	// Default to core API group if not specified
	applicationRefAPIGroup = ""
}
if j.Spec.StrategyRef.APIGroup != nil {
	strategyRefAPIGroup = *j.Spec.StrategyRef.APIGroup
} else {
	strategyRefAPIGroup = ""
}
if j.Spec.StorageRef.APIGroup != nil {
	storageRefAPIGroup = *j.Spec.StorageRef.APIGroup
} else {
	storageRefAPIGroup = ""
}

Comment on lines +105 to +108
values, ok := app.Object["spec"].(map[string]any)
if !ok {
values = map[string]any{}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The type assertion app.Object["spec"].(map[string]any) and subsequent fallback to an empty map if the assertion fails could mask potential issues. If the application object's spec is expected to always be a map[string]any, a failure here might indicate a malformed resource or an unexpected API version. It would be safer to log a warning or return an error in such cases, rather than silently proceeding with an empty map, which could lead to incorrect template rendering.

values, ok := app.Object["spec"].(map[string]any)
if !ok {
	log.Info("Application object 'spec' field is not a map[string]any, using empty values", "application", client.ObjectKeyFromObject(app))
	values = map[string]any{}
}

@lllamnyp lllamnyp mentioned this pull request Dec 12, 2025
19 tasks
Base automatically changed from feat/backup-jobdriver-api to main December 15, 2025 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.