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
4 changes: 3 additions & 1 deletion agent/app/dto/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ type ComposeCreate struct {
Path string `json:"path"`
Template uint `json:"template"`
Env string `json:"env"`
PullImage *bool `json:"pullImage,omitempty"`
ForcePull bool `json:"forcePull"`
}
type ComposeOperation struct {
Name string `json:"name" validate:"required"`
Expand All @@ -289,11 +289,13 @@ type ComposeOperation struct {
Force bool `json:"force"`
}
type ComposeUpdate struct {
TaskID string `json:"taskID"`
Name string `json:"name" validate:"required"`
Path string `json:"path" validate:"required"`
DetailPath string `json:"detailPath"`
Content string `json:"content" validate:"required"`
Env string `json:"env"`
ForcePull bool `json:"forcePull"`
}
type ComposeLogClean struct {
Name string `json:"name" validate:"required"`
Expand Down
58 changes: 33 additions & 25 deletions agent/app/service/container_compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,9 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) error {
if err := newComposeEnv(req.Path, req.Env); err != nil {
return err
}
pullImages := true
if req.PullImage != nil {
pullImages = *req.PullImage
}
go func() {
taskItem.AddSubTask(i18n.GetMsgByKey("ComposeCreate"), func(t *task.Task) error {
err := compose.UpWithTask(req.Path, t, pullImages)
err := compose.UpWithTask(req.Path, t, req.ForcePull)
t.LogWithStatus(i18n.GetMsgByKey("ComposeCreate"), err)
if err != nil {
_, _ = compose.Down(req.Path)
Expand Down Expand Up @@ -262,31 +258,43 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
if cmd.CheckIllegal(req.Name, req.Path) {
return buserr.New("ErrCmdIllegal")
}
oldFile, err := os.ReadFile(req.DetailPath)
if err != nil {
return fmt.Errorf("load file with path %s failed, %v", req.DetailPath, err)
}
file, err := os.OpenFile(req.DetailPath, os.O_WRONLY|os.O_TRUNC, 0640)
taskItem, err := task.NewTaskWithOps(req.Name, task.TaskUpdate, task.TaskScopeCompose, req.TaskID, 1)
if err != nil {
global.LOG.Errorf("new task for update compose failed, err: %v", err)
return err
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString(req.Content)
write.Flush()
go func() {
taskItem.AddSubTask(i18n.GetMsgByKey("TaskUpdate"), func(t *task.Task) error {
oldFile, err := os.ReadFile(req.DetailPath)
if err != nil {
return fmt.Errorf("load file with path %s failed, %v", req.DetailPath, err)
}
file, err := os.OpenFile(req.DetailPath, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
return err
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString(req.Content)
write.Flush()

global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.DetailPath)
if err := newComposeEnv(req.DetailPath, req.Env); err != nil {
return err
}
global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.DetailPath)
if err := newComposeEnv(req.DetailPath, req.Env); err != nil {
return err
}

if stdout, err := compose.Up(req.Path); err != nil {
global.LOG.Errorf("update failed when handle compose up, std: %s, err: %s, now try to recreate the old compose file", stdout, err)
if err := recreateCompose(string(oldFile), req.Path); err != nil {
return fmt.Errorf("update failed and recreate old compose file also failed, err: %v", err)
}
return fmt.Errorf("update failed when handle compose up, std: %v, err: %s", stdout, err)
}
if err := compose.UpWithTask(req.Path, t, req.ForcePull); err != nil {
global.LOG.Errorf("update failed when handle compose up, err: %s, now try to recreate the old compose file", err)
if err := recreateCompose(string(oldFile), req.Path); err != nil {
return fmt.Errorf("update failed and recreate old compose file also failed, err: %v", err)
}
return fmt.Errorf("update failed when handle compose up, err: %s", err)
}

return nil
}, nil)
_ = taskItem.Execute()
}()

return nil
}
Expand Down
46 changes: 35 additions & 11 deletions agent/utils/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ func Up(filePath string) (string, error) {
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
}

func UpWithTask(filePath string, task *task.Task, pullImages bool) error {
if !pullImages {
return cmd.NewCommandMgr(cmd.WithTask(*task)).RunBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
func UpWithTask(filePath string, task *task.Task, forcePull bool) error {
if err := pullComposeImages(filePath, forcePull, task); err != nil {
return err
}
return cmd.NewCommandMgr(cmd.WithTask(*task)).RunBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
}

func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
content, err := os.ReadFile(filePath)
if err != nil {
return err
Expand All @@ -57,11 +61,28 @@ func UpWithTask(filePath string, task *task.Task, pullImages bool) error {
if err != nil {
return err
}
errMsg := ""
for _, image := range images {
task.Log(i18n.GetWithName("PullImageStart", image))
if err = dockerCLi.PullImageWithProcess(task, image); err != nil {
errOur := err.Error()
if !forcePull {
if exist, _ := dockerCLi.ImageExists(image); exist {
if task != nil {
task.Log(i18n.GetMsgByKey("UseExistImage"))
}
continue
}
}

if task != nil {
task.Log(i18n.GetWithName("PullImageStart", image))
}
pullErr := error(nil)
if task != nil {
pullErr = dockerCLi.PullImageWithProcess(task, image)
} else {
pullErr = docker.PullImage(image)
}
if pullErr != nil {
errMsg := ""
errOur := pullErr.Error()
if errOur != "" {
if strings.Contains(errOur, "no such host") {
errMsg = i18n.GetMsgByKey("ErrNoSuchHost") + ":"
Expand All @@ -72,18 +93,21 @@ func UpWithTask(filePath string, task *task.Task, pullImages bool) error {
}
message := errMsg + errOur
installErr := errors.New(message)
task.LogFailedWithErr(i18n.GetMsgByKey("PullImage"), installErr)
if task != nil {
task.LogFailedWithErr(i18n.GetMsgByKey("PullImage"), installErr)
}
if exist, _ := dockerCLi.ImageExists(image); !exist {
return installErr
} else {
}
if task != nil {
task.Log(i18n.GetMsgByKey("UseExistImage"))
}
} else {
} else if task != nil {
task.Log(i18n.GetMsgByKey("PullImageSuccess"))
}
}

return cmd.NewCommandMgr(cmd.WithTask(*task)).RunBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
return nil
}

func Down(filePath string) (string, error) {
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/api/interface/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ export namespace Container {
path: string;
template: number;
env: string;
pullImage?: boolean;
forcePull: boolean;
}
export interface ComposeOperation {
name: string;
Expand All @@ -339,10 +339,12 @@ export namespace Container {
force: boolean;
}
export interface ComposeUpdate {
taskID: string;
name: string;
path: string;
content: string;
env: string;
forcePull: boolean;
createdBy: string;
}

Expand Down
17 changes: 13 additions & 4 deletions frontend/src/views/container/compose/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@
<span v-if="currentCompose.createdBy === 'Apps'" class="input-help">
{{ $t('container.composeEnvHelper2') }}
</span>
<div class="mt-2">
<el-checkbox v-model="form.forcePull" :label="$t('container.forcePull')" />
<span class="input-help">{{ $t('container.forcePullHelper') }}</span>
</div>

<el-button type="primary" class="mt-2" @click="onSubmitEdit">
{{ $t('commons.button.save') }}
Expand Down Expand Up @@ -336,8 +340,8 @@
<el-input placeholder="key=value" type="textarea" :rows="3" v-model="form.env" />
<span class="envTitle">{{ $t('commons.button.set') }}</span>
<el-form-item>
<el-checkbox v-model="form.pullImage" :label="$t('app.pullImage')" />
<span class="input-help">{{ $t('app.pullImageHelper') }}</span>
<el-checkbox v-model="form.forcePull" :label="$t('container.forcePull')" />
<span class="input-help">{{ $t('container.forcePullHelper') }}</span>
</el-form-item>
</el-form>

Expand Down Expand Up @@ -432,7 +436,7 @@ const form = reactive({
file: '',
template: null as number,
env: '',
pullImage: true,
forcePull: false,
});
const rules = reactive({
name: [Rules.requiredInput, Rules.composeName],
Expand Down Expand Up @@ -523,6 +527,7 @@ const loadDetail = async (row: Container.ComposeInfo, withRefresh: boolean) => {
if (currentCompose.value?.name === row.name && withRefresh !== true) {
return;
}
form.forcePull = false;
isOnCreate.value = false;
detailLoading.value = true;
currentCompose.value = row;
Expand Down Expand Up @@ -562,7 +567,7 @@ const onOpenDialog = async () => {
form.file = '';
form.template = null;
form.env = '';
form.pullImage = true;
form.forcePull = false;
loadPath();
loadTemplates();
};
Expand Down Expand Up @@ -683,18 +688,22 @@ const loadSize = async (row: any) => {
};

const onSubmitEdit = async () => {
const taskID = newUUID();
const param = {
taskID: taskID,
name: currentCompose.value.name,
path: currentCompose.value.path,
detailPath: currentYamlPath.value,
content: composeContent.value,
createdBy: currentCompose.value.createdBy,
env: env.value || '',
forcePull: form.forcePull,
};
loading.value = true;
await composeUpdate(param)
.then(async () => {
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
openTaskLog(taskID);
await search();
if (currentCompose.value) {
const updated = data.value.find((item) => item.name === currentCompose.value.name);
Expand Down
Loading