Skip to content

Conversation

@zuoxuesong-worker
Copy link
Contributor

What type of PR is this?

/kind feature

What this PR does / why we need it:

image module add copy func

Which issue(s) this PR fixes:

Fixes #

Special notes for reviewers:

image module add copy func

Does this PR introduced a user-facing change?

image module add copy func

Additional documentation, usage docs, etc.:


@kubesphere-prow kubesphere-prow bot added release-note kind/feature Categorizes issue or PR as related to a new feature. labels Nov 24, 2025
@kubesphere-prow
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: zuoxuesong-worker

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubesphere-prow kubesphere-prow bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 24, 2025
@gemini-code-assist
Copy link

Summary of Changes

Hello @zuoxuesong-worker, 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 significantly enhances the image module by introducing a new copy function, which allows for versatile image transfers. Users can now move container images between local file systems and remote registries with robust authentication and configuration options, streamlining image management workflows and expanding the module's utility.

Highlights

  • New Image Copy Functionality: Introduces a copy function to the image module, enabling flexible image transfers between local file systems and remote registries.
  • Flexible Copy Scenarios: Supports four distinct image copy operations: file-to-file, file-to-registry, registry-to-file, and registry-to-registry.
  • Unified Authentication Handling: Refactors authentication logic into a reusable authFunc to support both image pulling and the new copying operations.
  • Comprehensive Configuration Options: Provides detailed configuration for source and destination, including image manifests, paths, TLS verification, and authentication credentials.
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.

@kubesphere-prow kubesphere-prow bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Nov 24, 2025
Copy link

@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 copy function to the image module, allowing for copying container images between file systems and container registries. The implementation is comprehensive, covering file-to-file, file-to-hub, hub-to-file, and hub-to-hub scenarios. I've identified a few issues, including a critical bug in argument parsing, some potential panics from unhandled errors, and several areas in the documentation (both in markdown and code comments) that could be clarified or corrected. Overall, this is a great feature addition, and with a few fixes, it will be ready to merge.

cps.From.Type, _ = variable.StringVar(vars, cp, "from", "type")
cps.To.Type, _ = variable.StringVar(vars, cp, "to", "type")

srcPattern, _ := variable.StringVar(vars, cp, "to", "src_pattern")

Choose a reason for hiding this comment

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

critical

This line reads the variable to.src_pattern, but the documentation and struct field suggest it should be to.pattern. This is likely a copy-paste error from the push logic and will cause the pattern feature to not work as intended.

srcPattern, _ := variable.StringVar(vars, cp, "to", "pattern")

Comment on lines 450 to 502
_ = unstructured.SetNestedField(hostVars, src.Reference.Registry, "module", "image", "src", "reference", "registry")
_ = unstructured.SetNestedField(hostVars, src.Reference.Repository, "module", "image", "src", "reference", "repository")
_ = unstructured.SetNestedField(hostVars, src.Reference.Reference, "module", "image", "src", "reference", "reference")

Choose a reason for hiding this comment

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

high

The errors returned by unstructured.SetNestedField are ignored. If setting these template variables fails, it could lead to silent errors during template parsing. It's safer to handle these errors.

                if err := unstructured.SetNestedField(hostVars, src.Reference.Registry, "module", "image", "src", "reference", "registry"); err != nil {
					return err
				}
				if err := unstructured.SetNestedField(hostVars, src.Reference.Repository, "module", "image", "src", "reference", "repository"); err != nil {
					return err
				}
				if err := unstructured.SetNestedField(hostVars, src.Reference.Reference, "module", "image", "src", "reference", "reference"); err != nil {
					return err
				}

Comment on lines 589 to 591
a.Repo, _ = tmpl.ParseFunc(vars, a.Repo, func(b []byte) string { return string(b) })
a.Username, _ = tmpl.ParseFunc(vars, a.Username, func(b []byte) string { return string(b) })
a.Password, _ = tmpl.ParseFunc(vars, a.Password, func(b []byte) string { return string(b) })

Choose a reason for hiding this comment

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

high

Errors from tmpl.ParseFunc are being ignored when parsing authentication details. If template parsing fails, it could lead to silent authentication failures with empty credentials. These errors should be handled to prevent unexpected behavior.

Credential: authFunc(i.To.Auths),
}
default:
return errors.New(fmt.Sprintf("invalid image type %q", i.From.Type))

Choose a reason for hiding this comment

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

high

This error message uses i.From.Type, but it's inside the switch i.To.Type block. This appears to be a copy-paste error and should be i.To.Type to provide the correct context in case of an error.

return errors.New(fmt.Sprintf("invalid image type %q", i.To.Type))

- prometheus:v2.45.0
to:
type: hub
path: registry.example.com/{{ . }}

Choose a reason for hiding this comment

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

medium

The template {{ . }} is ambiguous and might be incorrect. It would be clearer and safer to use the full template variables, similar to the push example in the documentation, e.g., registry.example.com/{{ .module.image.src.reference.repository }}:{{ .module.image.src.reference.reference }}. This applies to other examples using this template as well.

Suggested change
path: registry.example.com/{{ . }}
path: registry.example.com/{{ .module.image.src.reference.repository }}:{{ .module.image.src.reference.reference }}

return err
}
if _, err = oras.Copy(ctx, src, src.Reference.Reference, dst, dst.Reference.Reference, oras.DefaultCopyOptions); err != nil {
return errors.Wrapf(err, "failed to push image %q to remote", img)

Choose a reason for hiding this comment

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

medium

The error message says "failed to push image", but this function performs a copy operation. A more accurate message would be "failed to copy image". This also applies to the error message on line 661.

return errors.Wrapf(err, "failed to copy image %q", img)

Comment on lines 586 to 602
pullAuths := make([]imageAuths, 0)
_ = variable.AnyVar(vars, cp, &pullAuths, "from", "auths")
for _, a := range pullAuths {
a.Repo, _ = tmpl.ParseFunc(vars, a.Repo, func(b []byte) string { return string(b) })
a.Username, _ = tmpl.ParseFunc(vars, a.Username, func(b []byte) string { return string(b) })
a.Password, _ = tmpl.ParseFunc(vars, a.Password, func(b []byte) string { return string(b) })
cps.From.Auths = append(cps.From.Auths, a)
}

pullAuths = make([]imageAuths, 0)
_ = variable.AnyVar(vars, cp, &pullAuths, "to", "auths")
for _, a := range pullAuths {
a.Repo, _ = tmpl.ParseFunc(vars, a.Repo, func(b []byte) string { return string(b) })
a.Username, _ = tmpl.ParseFunc(vars, a.Username, func(b []byte) string { return string(b) })
a.Password, _ = tmpl.ParseFunc(vars, a.Password, func(b []byte) string { return string(b) })
cps.To.Auths = append(cps.To.Auths, a)
}

Choose a reason for hiding this comment

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

medium

The logic for parsing auths is duplicated for from and to. This could be extracted into a helper function to improve maintainability and reduce code duplication.

| copy.to.type | 镜像目标类型 | 字符串 || - |
| copy.to.path | 镜像目标地址。如果类型为file,则为文件地址,如果类型为hub,则为仓库中的镜像地址 | 字符串 || - |
| copy.to.skip_tls_verify | 仅在hub类型中生效;目标镜像仓库是否跳过tls认证 | bool || - |
| copy.to.pattern | 正则表达式,过滤推送至目标的镜像 | 字符串 || - |

Choose a reason for hiding this comment

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

medium

The description for copy.to.pattern is incorrect. The implementation shows that this pattern is used to filter the source images listed in from.manifests, not the destination images. The description should be corrected to something like "正则表达式,过滤源镜像" (regex to filter source images).

| copy.from.auths.repo | 用于认证远程仓库的地址 | 字符串 || - |
| copy.from.auths.username | 用于认证远程仓库的用户名 | 字符串 || - |
| copy.from.auths.password | 用于认证远程仓库的密码 | 字符串 || - |
| copy.to | 模版语法,从本地目录镜像推送到的远程仓库镜像 | map || - |

Choose a reason for hiding this comment

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

medium

The description for copy.to seems to be a copy-paste from push.dest and is not entirely accurate for the copy context. A more generic description like "目标镜像信息" (destination image information) would be more appropriate.


if ia.copy != nil {
if err := ia.copy.copy(ctx, ha); err != nil {
return StdoutFailed, "failed to push image", err

Choose a reason for hiding this comment

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

medium

The error message says "failed to push image", but this is part of the copy functionality. For consistency, it should be "failed to copy image".

return StdoutFailed, "failed to copy image", err

@zuoxuesong-worker zuoxuesong-worker force-pushed the feat/image-module-copy branch 2 times, most recently from fa1510c to 8c30232 Compare November 27, 2025 07:46
@kubesphere-prow
Copy link

This PR has multiple commits, and the default merge method is: squash.
You can request commits to be merged using the label: tide/merge-method-merge

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: update some default config values (kubesphere#2866)

feat: update some default config values

Signed-off-by: [email protected] <[email protected]>

bugfix: fix artifact image tag set func (kubesphere#2870)

Signed-off-by: [email protected] <[email protected]>

feat: k8s add haproxy image default value (kubesphere#2869)

Signed-off-by: [email protected] <[email protected]>

feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854 (kubesphere#2855)

* feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>
Co-authored-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>
@zuoxuesong-worker zuoxuesong-worker force-pushed the feat/image-module-copy branch 3 times, most recently from faf482d to 114b21f Compare November 27, 2025 09:24
Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>
@sonarqubecloud
Copy link

@redscholar
Copy link
Contributor

/lgtm

@kubesphere-prow kubesphere-prow bot added the lgtm Indicates that a PR is ready to be merged. label Nov 28, 2025
@kubesphere-prow
Copy link

LGTM label has been added.

DetailsGit tree hash: 8d7a4bd73b1a480f7a815918a8044491f067c1cf

@ks-ci-bot ks-ci-bot merged commit 867aca2 into kubesphere:main Nov 28, 2025
7 checks passed
zuoxuesong-worker added a commit to zxs-test/kubekey that referenced this pull request Nov 28, 2025
Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func (kubesphere#2868)

* feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: update some default config values (kubesphere#2866)

feat: update some default config values

Signed-off-by: [email protected] <[email protected]>

bugfix: fix artifact image tag set func (kubesphere#2870)

Signed-off-by: [email protected] <[email protected]>

feat: k8s add haproxy image default value (kubesphere#2869)

Signed-off-by: [email protected] <[email protected]>

feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854 (kubesphere#2855)

* feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>
Co-authored-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

* feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>
zuoxuesong-worker added a commit to zxs-test/kubekey that referenced this pull request Nov 28, 2025
Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func (kubesphere#2868)

* feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: update some default config values (kubesphere#2866)

feat: update some default config values

Signed-off-by: [email protected] <[email protected]>

bugfix: fix artifact image tag set func (kubesphere#2870)

Signed-off-by: [email protected] <[email protected]>

feat: k8s add haproxy image default value (kubesphere#2869)

Signed-off-by: [email protected] <[email protected]>

feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854 (kubesphere#2855)

* feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>
Co-authored-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

* feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: add export copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func (kubesphere#2868)

* feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: update some default config values (kubesphere#2866)

feat: update some default config values

Signed-off-by: [email protected] <[email protected]>

bugfix: fix artifact image tag set func (kubesphere#2870)

Signed-off-by: [email protected] <[email protected]>

feat: k8s add haproxy image default value (kubesphere#2869)

Signed-off-by: [email protected] <[email protected]>

feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854 (kubesphere#2855)

* feat: kk 4.0 制品导出 支持skip_tls_verify 私仓镜像 kubesphere#2854

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

* feat: update image skip tls verify func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>
Co-authored-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

* feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

feat: image module add copy func

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. release-note size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants