1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-02-08 01:20:07 +08:00

feat: 创建应用增加 compose 文件配置功能 (#1105)

Refs https://github.com/1Panel-dev/1Panel/issues/301
This commit is contained in:
zhengkunwang223 2023-05-22 19:19:40 +08:00 committed by GitHub
parent 53600900f2
commit 74cfc11a37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 5 deletions

View File

@ -28,6 +28,8 @@ type AppContainerConfig struct {
MemoryUnit string `json:"memoryUnit"` MemoryUnit string `json:"memoryUnit"`
ContainerName string `json:"containerName"` ContainerName string `json:"containerName"`
AllowPort bool `json:"allowPort"` AllowPort bool `json:"allowPort"`
EditCompose bool `json:"editCompose"`
DockerCompose string `json:"dockerCompose"`
} }
type AppInstalledSearch struct { type AppInstalledSearch struct {

View File

@ -5,7 +5,7 @@ type AppDetail struct {
AppId uint `json:"appId" gorm:"type:integer;not null"` AppId uint `json:"appId" gorm:"type:integer;not null"`
Version string `json:"version" gorm:"type:varchar(64);not null"` Version string `json:"version" gorm:"type:varchar(64);not null"`
Params string `json:"-" gorm:"type:longtext;"` Params string `json:"-" gorm:"type:longtext;"`
DockerCompose string `json:"-" gorm:"type:longtext;"` DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"`
Status string `json:"status" gorm:"type:varchar(64);not null"` Status string `json:"status" gorm:"type:varchar(64);not null"`
LastVersion string `json:"lastVersion" gorm:"type:varchar(64);"` LastVersion string `json:"lastVersion" gorm:"type:varchar(64);"`
LastModified int `json:"lastModified" gorm:"type:integer;"` LastModified int `json:"lastModified" gorm:"type:integer;"`

View File

@ -268,9 +268,15 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
App: app, App: app,
} }
composeMap := make(map[string]interface{}) composeMap := make(map[string]interface{})
if req.EditCompose {
if err = yaml.Unmarshal([]byte(req.DockerCompose), &composeMap); err != nil {
return
}
} else {
if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil { if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil {
return return
} }
}
value, ok := composeMap["services"] value, ok := composeMap["services"]
if !ok { if !ok {

View File

@ -1120,6 +1120,9 @@ const message = {
'The application does not release the external access port by default, you can choose to release it in the advanced settings', 'The application does not release the external access port by default, you can choose to release it in the advanced settings',
upgradeStart: 'Start upgrading! Please refresh the page later', upgradeStart: 'Start upgrading! Please refresh the page later',
toFolder: 'Open the installation directory', toFolder: 'Open the installation directory',
editCompose: 'Edit compose file',
editComposeHelper: 'Editing the compose file may cause the software installation to fail',
composeNullErr: 'compose cannot be empty',
}, },
website: { website: {
website: 'Website', website: 'Website',

View File

@ -1113,6 +1113,9 @@ const message = {
appInstallWarn: '应用默认不放开外部访问端口可以在高级设置中选择放开', appInstallWarn: '应用默认不放开外部访问端口可以在高级设置中选择放开',
upgradeStart: '开始升级请稍后刷新页面', upgradeStart: '开始升级请稍后刷新页面',
toFolder: '打开安装目录', toFolder: '打开安装目录',
editCompose: '编辑 compose 文件',
editComposeHelper: '编辑 compose 文件可能导致软件安装失败',
composeNullErr: 'compose 不能为空',
}, },
website: { website: {
website: '网站', website: '网站',

View File

@ -150,6 +150,7 @@ const openInstall = () => {
params: appDetail.value.params, params: appDetail.value.params,
appDetailId: appDetail.value.id, appDetailId: appDetail.value.id,
app: app.value, app: app.value,
compose: appDetail.value.dockerCompose,
}; };
if (app.value.type === 'php') { if (app.value.type === 'php') {
router.push({ path: '/websites/runtime/php' }); router.push({ path: '/websites/runtime/php' });

View File

@ -7,9 +7,8 @@
:before-close="handleClose" :before-close="handleClose"
> >
<template #header> <template #header>
<Header :header="$t('app.install')" :back="handleClose" /> <Header :header="$t('app.install')" :back="handleClose"></Header>
</template> </template>
<el-row v-loading="loading"> <el-row v-loading="loading">
<el-col :span="22" :offset="1"> <el-col :span="22" :offset="1">
<el-alert type="info" :closable="false"> <el-alert type="info" :closable="false">
@ -66,6 +65,25 @@
<el-checkbox v-model="req.allowPort" :label="$t('app.allowPort')" size="large" /> <el-checkbox v-model="req.allowPort" :label="$t('app.allowPort')" size="large" />
<span class="input-help">{{ $t('app.allowPortHelper') }}</span> <span class="input-help">{{ $t('app.allowPortHelper') }}</span>
</el-form-item> </el-form-item>
<el-form-item prop="editCompose">
<el-checkbox v-model="req.editCompose" :label="$t('app.editCompose')" size="large" />
<span class="input-help">{{ $t('app.editComposeHelper') }}</span>
</el-form-item>
<div v-if="req.editCompose">
<codemirror
:autofocus="true"
placeholder=""
:indent-with-tab="true"
:tabSize="4"
style="height: 400px"
:lineWrapping="true"
:matchBrackets="true"
theme="cobalt"
:styleActiveLine="true"
:extensions="extensions"
v-model="req.dockerCompose"
/>
</div>
</div> </div>
</el-form> </el-form>
</el-col> </el-col>
@ -92,18 +110,26 @@ import { reactive, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import Params from '../params/index.vue'; import Params from '../params/index.vue';
import Header from '@/components/drawer-header/index.vue'; import Header from '@/components/drawer-header/index.vue';
import { Codemirror } from 'vue-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import i18n from '@/lang';
import { MsgError } from '@/utils/message';
const extensions = [javascript(), oneDark];
const router = useRouter(); const router = useRouter();
interface InstallRrops { interface InstallRrops {
appDetailId: number; appDetailId: number;
params?: App.AppParams; params?: App.AppParams;
app: any; app: any;
compose: string;
} }
const installData = ref<InstallRrops>({ const installData = ref<InstallRrops>({
appDetailId: 0, appDetailId: 0,
app: {}, app: {},
compose: '',
}); });
const open = ref(false); const open = ref(false);
const rules = ref<FormRules>({ const rules = ref<FormRules>({
@ -126,6 +152,8 @@ const initData = () => ({
memoryUnit: 'MB', memoryUnit: 'MB',
containerName: '', containerName: '',
allowPort: false, allowPort: false,
editCompose: false,
dockerCompose: '',
}); });
const req = reactive(initData()); const req = reactive(initData());
@ -140,6 +168,7 @@ const resetForm = () => {
paramForm.value.resetFields(); paramForm.value.resetFields();
} }
Object.assign(req, initData()); Object.assign(req, initData());
req.dockerCompose = installData.value.compose;
}; };
const acceptParams = (props: InstallRrops): void => { const acceptParams = (props: InstallRrops): void => {
@ -154,6 +183,10 @@ const submit = async (formEl: FormInstance | undefined) => {
if (!valid) { if (!valid) {
return; return;
} }
if (req.editCompose && req.dockerCompose == '') {
MsgError(i18n.global.t('app.composeNullErr'));
return;
}
req.appDetailId = installData.value.appDetailId; req.appDetailId = installData.value.appDetailId;
loading.value = true; loading.value = true;
InstallApp(req) InstallApp(req)