Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions agent/app/dto/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ type ImageBuild struct {
}

type ImagePull struct {
TaskID string `json:"taskID"`
RepoID uint `json:"repoID"`
ImageName string `json:"imageName" validate:"required"`
TaskID string `json:"taskID"`
RepoID uint `json:"repoID"`
ImageName []string `json:"imageName" validate:"required"`
}

type ImageTag struct {
Expand Down
18 changes: 11 additions & 7 deletions agent/app/service/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,17 +256,19 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
return err
}
defer client.Close()
imageItemName := strings.ReplaceAll(path.Base(req.ImageName), ":", "_")
taskItem, err := task.NewTaskWithOps(imageItemName, task.TaskPull, task.TaskScopeImage, req.TaskID, 1)
taskItem, err := task.NewTaskWithOps(strings.Join(req.ImageName, ","), task.TaskPull, task.TaskScopeImage, req.TaskID, 1)
if err != nil {
return fmt.Errorf("new task for image pull failed, err: %v", err)
}
go func() {
taskItem.AddSubTask(i18n.GetWithName("ImagePull", req.ImageName), func(t *task.Task) error {

for _, item := range req.ImageName {
itemName := strings.ReplaceAll(path.Base(item), ":", "_")
taskItem.AddSubTask(i18n.GetWithName("ImagePull", itemName), func(t *task.Task) error {
taskItem.Logf("----------------- %s -----------------", itemName)
options := image.PullOptions{}
imageName := req.ImageName
imageName := item
if req.RepoID == 0 {
hasAuth, authStr := loadAuthInfo(req.ImageName)
hasAuth, authStr := loadAuthInfo(item)
if hasAuth {
options.RegistryAuth = authStr
}
Expand All @@ -288,7 +290,7 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
options.RegistryAuth = authStr
}
imageName = repo.DownloadUrl + "/" + req.ImageName
imageName = repo.DownloadUrl + "/" + item
}
dockerCli := docker.NewClientWithExist(client)
err = dockerCli.PullImageWithProcessAndOptions(taskItem, imageName, options)
Expand All @@ -298,6 +300,8 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
}
return nil
}, nil)
}
go func() {
_ = taskItem.Execute()
}()
return nil
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/interface/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export namespace Container {
export interface ImagePull {
taskID: string;
repoID: number;
imageName: string;
imageName: Array<string>;
}
export interface ImageTag {
sourceID: string;
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,8 @@ const message = {

image: 'Image | Images',
imagePull: 'Pull',
imagePullHelper:
'Supports selecting multiple images to pull, press Enter after entering each image to continue',
imagePush: 'Push',
imagePushHelper:
'Detected that this image has multiple tags. Please confirm that the image name used for pushing is: {0}',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/es-es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,8 @@ const message = {
cache: 'Caché',
image: 'Imagen | Imágenes',
imagePull: 'Descargar',
imagePullHelper:
'Admite seleccionar múltiples imágenes para descargar, presione Enter después de ingresar cada imagen para continuar',
imagePush: 'Subir',
imagePushHelper:
'Detected that this image has multiple tags. Please confirm that the image name used for pushing is: {0}',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,7 @@ const message = {

image: '画像|画像',
imagePull: '引く',
imagePullHelper: '複数のイメージの選択をサポートし、各イメージ入力後にEnterキーを押して続行します',
imagePush: '押す',
imagePushHelper:
'このイメージに複数のタグが存在することが検出されました。プッシュ時に使用するイメージ名が以下であることを確認してください:{0}',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ const message = {
cache: '캐시',
image: '이미지 | 이미지들',
imagePull: '풀',
imagePullHelper: '여러 이미지 선택 풀링을 지원하며, 각 이미지 입력 후 Enter 키를 눌러 계속합니다',
imagePush: '푸시',
imagePushHelper:
'이 이미지에 여러 태그가 있는 것으로 감지되었습니다. 푸시 시 사용할 이미지 이름이 다음인지 확인하세요: {0}',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/ms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,8 @@ const message = {

image: 'Imej | Imej-imej',
imagePull: 'Tarik',
imagePullHelper:
'Menyokong pemilihan berbilang imej untuk ditarik, tekan Enter selepas memasukkan setiap imej untuk teruskan',
imagePush: 'Tekan',
imagePushHelper:
'Terdapat pengesahan bahawa imej ini mempunyai beberapa tag. Sila pastikan nama imej yang digunakan untuk menolak adalah: {0}',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/pt-br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,8 @@ const message = {
cache: 'Cache',
image: 'Imagem | Imagens',
imagePull: 'Puxar',
imagePullHelper:
'Suporta selecionar múltiplas imagens para puxar, pressione Enter após inserir cada imagem para continuar',
imagePush: 'Enviar',
imagePushHelper:
'Detectado que esta imagem possui múltiplas tags. Por favor, confirme que o nome da imagem usada para push é: {0}',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,8 @@ const message = {

image: 'Образ | Образы',
imagePull: 'Загрузить',
imagePullHelper:
'Поддерживает выбор нескольких образов для загрузки, нажмите Enter после ввода каждого образа для продолжения',
imagePush: 'Отправить',
imagePushHelper:
'Обнаружено, что у этого образа несколько тегов. Подтвердите, что имя образа, используемое для отправки: {0}',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,8 @@ const message = {

image: 'İmaj | İmajlar',
imagePull: 'Çek',
imagePullHelper:
'Birden fazla görüntü seçmeyi destekler, her görüntü girdikten sonra Entera basarak devam edin',
imagePush: 'Gönder',
imagePushHelper:
'Bu imgenin birden fazla etiketi olduğu tespit edildi. Lütfen gönderimde kullanılan imge adının şu olduğunu onaylayın: {0}',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/zh-Hant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ const message = {

image: '鏡像',
imagePull: '拉取鏡像',
imagePullHelper: '支援選擇拉取多個鏡像,輸入一組鏡像後回車繼續',
imagePush: '推送鏡像',
imagePushHelper: '檢測到該映像存在多個標籤,請確認推送時使用的映像名稱為:{0}',
imageDelete: '刪除鏡像',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,7 @@ const message = {

image: '镜像',
imagePull: '拉取镜像',
imagePullHelper: '支持选择拉取多个镜像,输入一组镜像后回车继续',
imagePush: '推送镜像',
imagePushHelper: '检测到该镜像存在多个标签,请确认推送时使用的镜像名称为:{0}',
imageDelete: '删除镜像',
Expand Down
45 changes: 32 additions & 13 deletions frontend/src/views/container/image/pull/index.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
<template>
<DrawerPro v-model="drawerVisible" :header="$t('container.imagePull')" @close="onCloseLog" size="large">
<el-form ref="formRef" label-position="top" :model="form">
<el-form ref="formRef" label-position="top" :model="form" :rules="rules">
<el-form-item :label="$t('app.source')">
<el-checkbox v-model="form.fromRepo">
{{ $t('container.imageRepo') }}
</el-checkbox>
</el-form-item>
<el-form-item
v-if="form.fromRepo"
:label="$t('container.repoName')"
:rules="Rules.requiredSelect"
prop="repoID"
>
<el-form-item v-if="form.fromRepo" :label="$t('container.repoName')" prop="repoID">
<el-select clearable style="width: 100%" filterable v-model="form.repoID">
<el-option v-for="item in repos" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
<el-form-item :label="$t('container.imageName')" :rules="Rules.imageName" prop="imageName">
<el-input v-model.trim="form.imageName">
<template v-if="form.fromRepo" #prepend>{{ loadDetailInfo(form.repoID) }}/</template>
</el-input>
<el-form-item :label="$t('container.imageName')" prop="imageName">
<el-input-tag v-model="form.imageName">
<template v-if="form.fromRepo" #prefix>{{ loadDetailInfo(form.repoID) }}/</template>
</el-input-tag>
<span class="input-help">{{ $t('container.imagePullHelper') }}</span>
</el-form-item>
</el-form>
<template #footer>
Expand Down Expand Up @@ -52,8 +48,31 @@ const form = reactive({
taskID: '',
fromRepo: true,
repoID: null as number,
imageName: '',
imageName: [],
});
const verifyImage = (rule: any, value: any, callback: any) => {
if (!value || value.length === 0) {
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
return;
}
for (const item of value) {
if (item === '' || typeof item === 'undefined' || item == null) {
callback(new Error(i18n.global.t('commons.rule.imageName')));
} else {
const reg = /^[a-zA-Z0-9]{1}[a-z:@A-Z0-9_/.-]{0,255}$/;
if (!reg.test(item) && item !== '') {
callback(new Error(i18n.global.t('commons.rule.imageName')));
return;
}
}
}
callback();
};
const rules = reactive({
imageName: [{ validator: verifyImage, trigger: 'blur', required: true }],
repoID: Rules.requiredSelect,
});

const taskLogRef = ref();

interface DialogProps {
Expand All @@ -64,7 +83,7 @@ const repos = ref();
const acceptParams = async (params: DialogProps): Promise<void> => {
drawerVisible.value = true;
form.fromRepo = true;
form.imageName = '';
form.imageName = [];
repos.value = params.repos;
form.repoID = 1;
for (const item of repos.value) {
Expand Down
Loading