diff --git a/docs/zh/modules/image.md b/docs/zh/modules/image.md index 8d8d9054..8667a4f2 100644 --- a/docs/zh/modules/image.md +++ b/docs/zh/modules/image.md @@ -28,23 +28,11 @@ image模块允许用户下载镜像到本地目录或上传镜像到远程目录 | push.dest | 模版语法,从本地目录镜像推送到的远程仓库镜像 | map | 否 | - | | copy | 模版语法,将镜像在文件系统和镜像仓库内相互复制 | map | 否 | - | | copy.from | 模版语法,源镜像信息 | map | 否 | - | -| copy.from.type | 镜像源类型 | 字符串 | 否 | - | -| copy.from.path | 镜像源地址。如果类型为file,则为文件地址,如果类型为hub,则为镜像仓库地址 | 字符串 | 否 | - | -| copy.from.skip_tls_verify | 仅在hub类型中生效;源镜像仓库是否跳过tls认证 | bool | 否 | - | +| copy.from.path | 镜像源文件路径 | 字符串 | 否 | - | | copy.from.manifests | 源镜像列表 | 字符串数组 | 否 | - | -| copy.from.auths | 远程仓库的认证信息 | Object数组 | 否 | - | -| copy.from.auths.repo | 用于认证远程仓库的地址 | 字符串 | 否 | - | -| copy.from.auths.username | 用于认证远程仓库的用户名 | 字符串 | 否 | - | -| copy.from.auths.password | 用于认证远程仓库的密码 | 字符串 | 否 | - | | copy.to | 模版语法,从本地目录镜像推送到的远程仓库镜像 | map | 否 | - | -| copy.to.type | 镜像目标类型 | 字符串 | 否 | - | -| copy.to.path | 镜像目标地址。如果类型为file,则为文件地址,如果类型为hub,则为仓库中的镜像地址 | 字符串 | 否 | - | -| copy.to.skip_tls_verify | 仅在hub类型中生效;目标镜像仓库是否跳过tls认证 | bool | 否 | - | -| copy.to.pattern | 正则表达式,过滤推送至目标的镜像 | 字符串 | 否 | - | -| copy.to.auths | 远程仓库的认证信息 | Object数组 | 否 | - | -| copy.to.auths.repo | 用于认证远程仓库的地址 | 字符串 | 否 | - | -| copy.to.auths.username | 用于认证远程仓库的用户名 | 字符串 | 否 | - | -| copy.to.auths.password | 用于认证远程仓库的密码 | 字符串 | 否 | - | +| copy.to.path | 镜像目标文件路径 | 字符串 | 否 | - | +| copy.to.pattern | 正则表达式,过滤复制至目标的镜像 | 字符串 | 否 | - | 每个本地目录存放的镜像对应一个dest镜像。 @@ -100,64 +88,9 @@ docker.io/kubesphere/ks-console:3.19 => hub.kubekey/kubesphere/ks-console:v4.1.3 image: copy: from: - type: file path: "/tmp/images/" manifests: - docker.io/calico/apiserver:v3.28.2 to: - type: file path: "/tmp/others/images/" -``` - -4. 将镜像从文件系统推送至镜像仓库 -```yaml -- name: file to hub - image: - copy: - from: - type: file - path: "/tmp/images/" - manifests: - - docker.io/calico/apiserver:v3.28.2 - to: - type: hub - path: >- - hub.kubekey/{{ .module.image.src.reference.repository }}:{{ .module.image.src.reference.reference }} -``` - -5. 将镜像从仓库推送至文件系统 -```yaml -- name: hub to file - image: - copy: - from: - type: hub - auths: - - repo: docker.io - username: DockerAccount - password: DockerPassword - manifests: - - docker.io/calico/apiserver:v3.28.2 - to: - type: file - path: /tmp/images/ -``` - -6. 将镜像从仓库推送至其他仓库 -```yaml -- name: hub to hub - image: - copy: - from: - type: hub - auths: - - repo: docker.io - username: DockerAccount - password: DockerPassword - manifests: - - docker.io/calico/apiserver:v3.28.2 - to: - type: hub - path: >- - hub.kubekey/{{ .module.image.src.reference.repository }}:{{ .module.image.src.reference.reference }} ``` \ No newline at end of file diff --git a/pkg/modules/image.go b/pkg/modules/image.go index 8ce590f9..aa9a78c7 100644 --- a/pkg/modules/image.go +++ b/pkg/modules/image.go @@ -129,13 +129,13 @@ Usage Examples in Playbook Tasks: - name: file to file image: copy: - from: - path: "/path/from/images" - manifests: - - nginx:latest - - prometheus:v2.45.0 - to: - path: /path/to/images + from: + path: "/path/from/images" + manifests: + - nginx:latest + - prometheus:v2.45.0 + to: + path: /path/to/images ``` Return Values: @@ -211,6 +211,20 @@ func (i imagePullArgs) pull(ctx context.Context, platform string) error { return nil } +func dockerHostParser(img string) string { + // if image is like docker.io/xxx/xxx:tag, then download by pull func will store it to registry-1.docker.io + // so we should change host from docker.io to registry-1.docker.io + splitedImg := strings.Split(img, "/") + if len(splitedImg) == 1 { + return img + } + if splitedImg[0] != "docker.io" { + return img + } + splitedImg[0] = "registry-1.docker.io" + return strings.Join(splitedImg, "/") +} + func authFunc(auths []imageAuth) func(ctx context.Context, hostport string) (auth.Credential, error) { var creds = make(map[string]auth.Credential) for _, inputAuth := range auths { @@ -340,14 +354,9 @@ type imageCopyTargetArgs struct { func (i *imageCopyArgs) parseFromVars(vars, cp map[string]any) error { i.From.manifests, _ = variable.StringSliceVar(vars, cp, "from", "manifests") - fromPath, _ := variable.PrintVar(cp, "from", "path") - if fromStr, ok := fromPath.(string); !ok { - return errors.New("\"copy.to.path\" must be a string") - } else if fromStr == "" { - return errors.New("\"copy.to.path\" should not be empty") - } else { - i.From.Path = fromStr - } + + i.From.Path, _ = variable.StringVar(vars, cp, "from", "path") + toPath, _ := variable.PrintVar(cp, "to", "path") if destStr, ok := toPath.(string); !ok { return errors.New("\"copy.to.path\" must be a string") @@ -367,20 +376,32 @@ func (i *imageCopyArgs) parseFromVars(vars, cp map[string]any) error { return nil } -func (i *imageCopyArgs) copy(ctx context.Context, _ map[string]any) error { +func (i *imageCopyArgs) copy(ctx context.Context, hostVars map[string]any) error { if sts, err := os.Stat(i.From.Path); err != nil || !sts.IsDir() { return errors.New("\"copy.from.path\" must be a exist directory") } for _, img := range i.From.manifests { + img = normalizeImageNameSimple(img) if i.To.Pattern != nil && !i.To.Pattern.MatchString(img) { // skip continue } - src, err := newLocalRepository(img, i.From.Path) + src, err := newLocalRepository(dockerHostParser(img), i.From.Path) if err != nil { return err } - dst, err := newLocalRepository(filepath.Join(src.Reference.Registry, src.Reference.Repository)+":"+src.Reference.Reference, i.To.Path) + dest := i.To.Path + if kkprojectv1.IsTmplSyntax(dest) { + // add temporary variable + _ = 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") + dest, err = tmpl.ParseFunc(hostVars, dest, func(b []byte) string { return string(b) }) + if err != nil { + return err + } + } + dst, err := newLocalRepository(filepath.Join(src.Reference.Registry, src.Reference.Repository)+":"+src.Reference.Reference, dest) if err != nil { return err }