mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-01-13 02:24:25 +08:00
parent
129e864975
commit
4eb264bea4
14 changed files with 63 additions and 24 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -298,6 +300,8 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
|
|||
}
|
||||
return nil
|
||||
}, nil)
|
||||
}
|
||||
go func() {
|
||||
_ = taskItem.Execute()
|
||||
}()
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ export namespace Container {
|
|||
export interface ImagePull {
|
||||
taskID: string;
|
||||
repoID: number;
|
||||
imageName: string;
|
||||
imageName: Array<string>;
|
||||
}
|
||||
export interface ImageTag {
|
||||
sourceID: string;
|
||||
|
|
|
|||
|
|
@ -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}',
|
||||
|
|
|
|||
|
|
@ -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}',
|
||||
|
|
|
|||
|
|
@ -852,6 +852,7 @@ const message = {
|
|||
|
||||
image: '画像|画像',
|
||||
imagePull: '引く',
|
||||
imagePullHelper: '複数のイメージの選択をサポートし、各イメージ入力後にEnterキーを押して続行します',
|
||||
imagePush: '押す',
|
||||
imagePushHelper:
|
||||
'このイメージに複数のタグが存在することが検出されました。プッシュ時に使用するイメージ名が以下であることを確認してください:{0}',
|
||||
|
|
|
|||
|
|
@ -844,6 +844,7 @@ const message = {
|
|||
cache: '캐시',
|
||||
image: '이미지 | 이미지들',
|
||||
imagePull: '풀',
|
||||
imagePullHelper: '여러 이미지 선택 풀링을 지원하며, 각 이미지 입력 후 Enter 키를 눌러 계속합니다',
|
||||
imagePush: '푸시',
|
||||
imagePushHelper:
|
||||
'이 이미지에 여러 태그가 있는 것으로 감지되었습니다. 푸시 시 사용할 이미지 이름이 다음인지 확인하세요: {0}',
|
||||
|
|
|
|||
|
|
@ -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}',
|
||||
|
|
|
|||
|
|
@ -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}',
|
||||
|
|
|
|||
|
|
@ -865,6 +865,8 @@ const message = {
|
|||
|
||||
image: 'Образ | Образы',
|
||||
imagePull: 'Загрузить',
|
||||
imagePullHelper:
|
||||
'Поддерживает выбор нескольких образов для загрузки, нажмите Enter после ввода каждого образа для продолжения',
|
||||
imagePush: 'Отправить',
|
||||
imagePushHelper:
|
||||
'Обнаружено, что у этого образа несколько тегов. Подтвердите, что имя образа, используемое для отправки: {0}',
|
||||
|
|
|
|||
|
|
@ -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}',
|
||||
|
|
|
|||
|
|
@ -840,6 +840,7 @@ const message = {
|
|||
|
||||
image: '鏡像',
|
||||
imagePull: '拉取鏡像',
|
||||
imagePullHelper: '支援選擇拉取多個鏡像,輸入一組鏡像後回車繼續',
|
||||
imagePush: '推送鏡像',
|
||||
imagePushHelper: '檢測到該映像存在多個標籤,請確認推送時使用的映像名稱為:{0}',
|
||||
imageDelete: '刪除鏡像',
|
||||
|
|
|
|||
|
|
@ -839,6 +839,7 @@ const message = {
|
|||
|
||||
image: '镜像',
|
||||
imagePull: '拉取镜像',
|
||||
imagePullHelper: '支持选择拉取多个镜像,输入一组镜像后回车继续',
|
||||
imagePush: '推送镜像',
|
||||
imagePushHelper: '检测到该镜像存在多个标签,请确认推送时使用的镜像名称为:{0}',
|
||||
imageDelete: '删除镜像',
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue