mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-15 04:00:00 +08:00
feat: 运行环境支持增加环境变量 (#6652)
Refs https://github.com/1Panel-dev/1Panel/issues/4262
This commit is contained in:
parent
6c3311ba3c
commit
e3329597bc
17 changed files with 291 additions and 233 deletions
|
@ -1,6 +1,8 @@
|
|||
package request
|
||||
|
||||
import "github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
)
|
||||
|
||||
type RuntimeSearch struct {
|
||||
dto.PageInfo
|
||||
|
@ -27,6 +29,12 @@ type NodeConfig struct {
|
|||
Clean bool `json:"clean"`
|
||||
Port int `json:"port"`
|
||||
ExposedPorts []ExposedPort `json:"exposedPorts"`
|
||||
Environments []Environment `json:"environments"`
|
||||
}
|
||||
|
||||
type Environment struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type ExposedPort struct {
|
||||
|
|
|
@ -26,6 +26,7 @@ type RuntimeDTO struct {
|
|||
Port int `json:"port"`
|
||||
Path string `json:"path"`
|
||||
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
|
||||
Environments []request.Environment `json:"environments"`
|
||||
}
|
||||
|
||||
type PackageScripts struct {
|
||||
|
|
|
@ -618,10 +618,6 @@ func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, erro
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//app, err := appRepo.GetFirst(commonRepo.WithByID(appInstall.AppId))
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(appInstall.ID))
|
||||
for _, website := range websites {
|
||||
res = append(res, dto.AppResource{
|
||||
|
@ -629,17 +625,14 @@ func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, erro
|
|||
Name: website.PrimaryDomain,
|
||||
})
|
||||
}
|
||||
//TODO 根据运行环境情况处理
|
||||
//if app.Type == constant.Runtime {
|
||||
// resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID), commonRepo.WithByFrom(constant.AppResourceLocal))
|
||||
// for _, resource := range resources {
|
||||
// linkInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(resource.AppInstallId))
|
||||
// res = append(res, dto.AppResource{
|
||||
// Type: "app",
|
||||
// Name: linkInstall.Name,
|
||||
// })
|
||||
// }
|
||||
//}
|
||||
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID), commonRepo.WithByFrom(constant.AppResourceLocal))
|
||||
for _, resource := range resources {
|
||||
linkInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(resource.AppInstallId))
|
||||
res = append(res, dto.AppResource{
|
||||
Type: "app",
|
||||
Name: linkInstall.Name,
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
|
|||
return nil, err
|
||||
}
|
||||
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo:
|
||||
runtime.Port = create.Port
|
||||
runtime.Port = int(create.Params["port"].(float64))
|
||||
if err = handleNodeAndJava(create, runtime, fileOp, appVersionDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
|
|||
}
|
||||
for k, v := range envs {
|
||||
switch k {
|
||||
case "NODE_APP_PORT", "PANEL_APP_PORT_HTTP", "JAVA_APP_PORT", "GO_APP_PORT":
|
||||
case "NODE_APP_PORT", "PANEL_APP_PORT_HTTP", "JAVA_APP_PORT", "GO_APP_PORT", "APP_PORT", "port":
|
||||
port, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -379,6 +379,14 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
|
|||
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
|
||||
res.Source = v
|
||||
}
|
||||
composeByte, err := files.NewFileOp().GetContent(runtime.GetComposePath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Environments, err = getDockerComposeEnvironments(composeByte)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
|
@ -395,6 +403,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
|
|||
}
|
||||
oldImage := runtime.Image
|
||||
oldEnv := runtime.Env
|
||||
req.Port = int(req.Params["port"].(float64))
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID))
|
||||
|
@ -451,6 +460,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
|
|||
Port: req.Port,
|
||||
Install: true,
|
||||
ExposedPorts: req.ExposedPorts,
|
||||
Environments: req.Environments,
|
||||
},
|
||||
}
|
||||
composeContent, envContent, _, err := handleParams(create, projectDir)
|
||||
|
|
|
@ -207,6 +207,33 @@ func getRuntimeEnv(envStr, key string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func getRuntimeEnvironments(composeByte []byte) ([]request.Environment, error) {
|
||||
var environments []request.Environment
|
||||
var composeMap map[string]interface{}
|
||||
if err := yaml.Unmarshal(composeByte, &composeMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
services, ok := composeMap["services"].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, buserr.New(constant.ErrFileParse)
|
||||
}
|
||||
for _, service := range services {
|
||||
envs, ok := service.(map[string]interface{})["environment"].([]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, env := range envs {
|
||||
envStr := env.(string)
|
||||
envArray := strings.Split(envStr, "=")
|
||||
environments = append(environments, request.Environment{
|
||||
Key: envArray[0],
|
||||
Value: envArray[1],
|
||||
})
|
||||
}
|
||||
}
|
||||
return environments, nil
|
||||
}
|
||||
|
||||
func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) {
|
||||
runtimePath := runtime.GetPath()
|
||||
composePath := runtime.GetComposePath()
|
||||
|
@ -315,6 +342,11 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
for k := range env {
|
||||
if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") {
|
||||
delete(env, k)
|
||||
}
|
||||
}
|
||||
switch create.Type {
|
||||
case constant.RuntimePHP:
|
||||
create.Params["IMAGE_NAME"] = create.Image
|
||||
|
@ -357,7 +389,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
|
|||
create.Params["RUN_INSTALL"] = "0"
|
||||
}
|
||||
create.Params["CONTAINER_PACKAGE_URL"] = create.Source
|
||||
|
||||
create.Params["NODE_APP_PORT"] = create.Params["APP_PORT"]
|
||||
composeContent, err = handleCompose(env, composeContent, create, projectDir)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -366,6 +398,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
|
|||
create.Params["CODE_DIR"] = create.CodeDir
|
||||
create.Params["JAVA_VERSION"] = create.Version
|
||||
create.Params["PANEL_APP_PORT_HTTP"] = create.Port
|
||||
create.Params["JAVA_APP_PORT"] = create.Params["APP_PORT"]
|
||||
composeContent, err = handleCompose(env, composeContent, create, projectDir)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -374,6 +407,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
|
|||
create.Params["CODE_DIR"] = create.CodeDir
|
||||
create.Params["GO_VERSION"] = create.Version
|
||||
create.Params["PANEL_APP_PORT_HTTP"] = create.Port
|
||||
create.Params["GO_APP_PORT"] = create.Params["APP_PORT"]
|
||||
composeContent, err = handleCompose(env, composeContent, create, projectDir)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -416,7 +450,6 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
|
|||
_, ok := serviceValue["ports"].([]interface{})
|
||||
if ok {
|
||||
var ports []interface{}
|
||||
|
||||
switch create.Type {
|
||||
case constant.RuntimeNode:
|
||||
ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${NODE_APP_PORT}")
|
||||
|
@ -426,7 +459,6 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
|
|||
ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${GO_APP_PORT}")
|
||||
|
||||
}
|
||||
|
||||
for i, port := range create.ExposedPorts {
|
||||
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
|
||||
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
|
||||
|
@ -438,6 +470,13 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
|
|||
}
|
||||
serviceValue["ports"] = ports
|
||||
}
|
||||
var environments []interface{}
|
||||
for _, e := range create.Environments {
|
||||
environments = append(environments, fmt.Sprintf("%s:%s", e.Key, e.Value))
|
||||
}
|
||||
if len(environments) > 0 {
|
||||
serviceValue["environment"] = environments
|
||||
}
|
||||
break
|
||||
}
|
||||
for k := range env {
|
||||
|
@ -582,3 +621,30 @@ func restartRuntime(runtime *model.Runtime) (err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getDockerComposeEnvironments(yml []byte) ([]request.Environment, error) {
|
||||
var (
|
||||
composeProject docker.ComposeProject
|
||||
err error
|
||||
)
|
||||
err = yaml.Unmarshal(yml, &composeProject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []request.Environment
|
||||
for _, service := range composeProject.Services {
|
||||
for _, env := range service.Environment {
|
||||
envArray := strings.Split(env, ":")
|
||||
key := envArray[0]
|
||||
value := ""
|
||||
if len(envArray) > 1 {
|
||||
value = envArray[1]
|
||||
}
|
||||
res = append(res, request.Environment{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ type ComposeProject struct {
|
|||
}
|
||||
|
||||
type Service struct {
|
||||
Image string `yaml:"image"`
|
||||
Image string `yaml:"image"`
|
||||
Environment []string `yaml:"environment"`
|
||||
}
|
||||
|
||||
func replaceEnvVariables(input string, envVars map[string]string) string {
|
||||
|
|
|
@ -39,6 +39,7 @@ export namespace Runtime {
|
|||
source?: string;
|
||||
path?: string;
|
||||
exposedPorts?: ExposedPort[];
|
||||
environments?: Environment[];
|
||||
}
|
||||
|
||||
export interface RuntimeCreate {
|
||||
|
@ -56,6 +57,7 @@ export namespace Runtime {
|
|||
codeDir?: string;
|
||||
port?: number;
|
||||
exposedPorts?: ExposedPort[];
|
||||
environments?: Environment[];
|
||||
}
|
||||
|
||||
export interface ExposedPort {
|
||||
|
@ -63,6 +65,11 @@ export namespace Runtime {
|
|||
containerPort: number;
|
||||
}
|
||||
|
||||
export interface Environment {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface RuntimeUpdate {
|
||||
name: string;
|
||||
appDetailID: number;
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
{{ $t('file.download') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="mt-2.5">
|
||||
<highlightjs
|
||||
ref="editorRef"
|
||||
|
@ -57,8 +56,8 @@ import { GlobalStore } from '@/store';
|
|||
import screenfull from 'screenfull';
|
||||
import { DownloadFile } from '@/api/modules/container';
|
||||
|
||||
const logInfo = ref();
|
||||
const terminalSocket = ref<WebSocket>();
|
||||
const logInfo = ref('');
|
||||
const logSocket = ref<WebSocket>();
|
||||
const open = ref(false);
|
||||
const resource = ref('');
|
||||
const globalStore = GlobalStore();
|
||||
|
@ -78,7 +77,7 @@ const logSearch = reactive({
|
|||
});
|
||||
|
||||
const handleClose = () => {
|
||||
terminalSocket.value?.send('close conn');
|
||||
logSocket.value?.send('close conn');
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
|
@ -120,16 +119,16 @@ const searchLogs = async () => {
|
|||
MsgError(i18n.global.t('container.linesHelper'));
|
||||
return;
|
||||
}
|
||||
terminalSocket.value?.send('close conn');
|
||||
terminalSocket.value?.close();
|
||||
logSocket.value?.send('close conn');
|
||||
logSocket.value?.close();
|
||||
logInfo.value = '';
|
||||
const href = window.location.href;
|
||||
const protocol = href.split('//')[0] === 'http:' ? 'ws' : 'wss';
|
||||
const host = href.split('//')[1].split('/')[0];
|
||||
terminalSocket.value = new WebSocket(
|
||||
logSocket.value = new WebSocket(
|
||||
`${protocol}://${host}/api/v2/containers/compose/search/log?compose=${logSearch.compose}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}`,
|
||||
);
|
||||
terminalSocket.value.onmessage = (event) => {
|
||||
logSocket.value.onmessage = (event) => {
|
||||
logInfo.value += event.data;
|
||||
nextTick(() => {
|
||||
console.log(scrollerElement.value);
|
||||
|
@ -179,7 +178,6 @@ const acceptParams = (props: DialogProps): void => {
|
|||
logSearch.mode = timeOptions.value[3].value;
|
||||
logSearch.isWatch = true;
|
||||
resource.value = props.resource;
|
||||
searchLogs();
|
||||
open.value = true;
|
||||
if (!mobile.value) {
|
||||
screenfull.on('change', () => {
|
||||
|
@ -188,6 +186,7 @@ const acceptParams = (props: DialogProps): void => {
|
|||
}
|
||||
nextTick(() => {
|
||||
if (editorRef.value) {
|
||||
searchLogs();
|
||||
scrollerElement.value = editorRef.value.$el as HTMLElement;
|
||||
let hljsDom = scrollerElement.value.querySelector('.hljs') as HTMLElement;
|
||||
hljsDom.style['min-height'] = '300px';
|
||||
|
|
|
@ -2530,6 +2530,9 @@ const message = {
|
|||
start_servers: 'number of processes created at startup',
|
||||
min_spare_servers: 'minimum number of idle processes',
|
||||
max_spare_servers: 'maximum number of idle processes',
|
||||
envKey: 'Name',
|
||||
envValue: 'Value',
|
||||
environment: 'Environment Variable',
|
||||
},
|
||||
process: {
|
||||
pid: 'Process ID',
|
||||
|
|
|
@ -2347,6 +2347,9 @@ const message = {
|
|||
start_servers: '啟動時所建立的進程數',
|
||||
min_spare_servers: '最小空閒行程數',
|
||||
max_spare_servers: '最大空閒行程數',
|
||||
envKey: '名稱',
|
||||
envValue: '值',
|
||||
environment: '環境變數',
|
||||
},
|
||||
process: {
|
||||
pid: '進程ID',
|
||||
|
|
|
@ -2346,6 +2346,9 @@ const message = {
|
|||
start_servers: '启动时创建的进程数',
|
||||
min_spare_servers: '最小空闲进程数',
|
||||
max_spare_servers: '最大空闲进程数',
|
||||
envKey: '名称',
|
||||
envValue: '值',
|
||||
environment: '环境变量',
|
||||
},
|
||||
process: {
|
||||
pid: '进程ID',
|
||||
|
|
57
frontend/src/views/website/runtime/environment/index.vue
Normal file
57
frontend/src/views/website/runtime/environment/index.vue
Normal file
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="4">
|
||||
<el-button @click="addEnv">{{ $t('commons.button.add') }}{{ $t('runtime.environment') }}</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="mt-1.5">
|
||||
<el-row :gutter="20" v-for="(env, index) in environments" :key="index">
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="`environments.${index}.key`" :rules="rules.value">
|
||||
<el-input v-model="env.key" :placeholder="$t('runtime.envKey')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="`environments.${index}.value`" :rules="rules.value">
|
||||
<el-input v-model="env.value" :placeholder="$t('runtime.envValue')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="removeEnv(index)" link>
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, reactive } from 'vue';
|
||||
import { FormRules } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
|
||||
const props = defineProps({
|
||||
environments: {
|
||||
type: Array<Runtime.Environment>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
value: [Rules.requiredInput],
|
||||
});
|
||||
|
||||
const addEnv = () => {
|
||||
props.environments.push({
|
||||
key: '',
|
||||
value: '',
|
||||
});
|
||||
};
|
||||
|
||||
const removeEnv = (index: number) => {
|
||||
props.environments.splice(index, 1);
|
||||
};
|
||||
</script>
|
|
@ -77,67 +77,18 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.appPort')" prop="params.GO_APP_PORT">
|
||||
<el-input v-model.number="runtime.params['GO_APP_PORT']" />
|
||||
<span class="input-help">{{ $t('runtime.appPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.externalPort')" prop="port">
|
||||
<el-input v-model.number="runtime.port" />
|
||||
<span class="input-help">{{ $t('runtime.externalPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('commons.button.add') + $t('commons.table.port')">
|
||||
<el-button @click="addPort">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('app.allowPort')" prop="params.HOST_IP">
|
||||
<el-switch
|
||||
v-model="runtime.params['HOST_IP']"
|
||||
:active-value="'0.0.0.0'"
|
||||
:inactive-value="'127.0.0.1'"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-for="(port, index) of runtime.exposedPorts" :key="index">
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="'exposedPorts.' + index + '.containerPort'" :rules="rules.params.GO_APP_PORT">
|
||||
<el-input v-model.number="port.containerPort" :placeholder="$t('runtime.appPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="'exposedPorts.' + index + '.hostPort'" :rules="rules.params.GO_APP_PORT">
|
||||
<el-input v-model.number="port.hostPort" :placeholder="$t('runtime.externalPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="removePort(index)" link>
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<PortConfig :params="runtime.params" :exposedPorts="runtime.exposedPorts" :rules="rules" />
|
||||
<Environment :environments="runtime.environments" />
|
||||
<el-form-item :label="$t('app.containerName')" prop="params.CONTAINER_NAME">
|
||||
<el-input v-model.trim="runtime.params['CONTAINER_NAME']"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit(runtimeForm)" :disabled="loading">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit(runtimeForm)" :disabled="loading">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
</template>
|
||||
|
@ -152,6 +103,8 @@ import i18n from '@/lang';
|
|||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import PortConfig from '@/views/website/runtime/port/index.vue';
|
||||
import Environment from '@/views/website/runtime/environment/index.vue';
|
||||
|
||||
interface OperateRrops {
|
||||
id?: number;
|
||||
|
@ -185,6 +138,7 @@ const initData = (type: string) => ({
|
|||
codeDir: '/',
|
||||
port: 8080,
|
||||
exposedPorts: [],
|
||||
environments: [],
|
||||
});
|
||||
let runtime = reactive<Runtime.RuntimeCreate>(initData('go'));
|
||||
const rules = ref<any>({
|
||||
|
@ -194,7 +148,7 @@ const rules = ref<any>({
|
|||
port: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
source: [Rules.requiredSelect],
|
||||
params: {
|
||||
GO_APP_PORT: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
APP_PORT: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
HOST_IP: [Rules.requiredSelect],
|
||||
CONTAINER_NAME: [Rules.requiredInput, Rules.containerName],
|
||||
EXEC_SCRIPT: [Rules.requiredInput],
|
||||
|
@ -204,7 +158,7 @@ const scripts = ref<Runtime.NodeScripts[]>([]);
|
|||
const em = defineEmits(['close']);
|
||||
|
||||
watch(
|
||||
() => runtime.params['GO_APP_PORT'],
|
||||
() => runtime.params['APP_PORT'],
|
||||
(newVal) => {
|
||||
if (newVal && mode.value == 'create') {
|
||||
runtime.port = newVal;
|
||||
|
@ -233,17 +187,6 @@ const getPath = (codeDir: string) => {
|
|||
runtime.codeDir = codeDir;
|
||||
};
|
||||
|
||||
const addPort = () => {
|
||||
runtime.exposedPorts.push({
|
||||
hostPort: undefined,
|
||||
containerPort: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const removePort = (index: number) => {
|
||||
runtime.exposedPorts.splice(index, 1);
|
||||
};
|
||||
|
||||
const searchApp = (appID: number) => {
|
||||
SearchApp(appReq).then((res) => {
|
||||
apps.value = res.data.items || [];
|
||||
|
@ -303,7 +246,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||
if (runtime.exposedPorts && runtime.exposedPorts.length > 0) {
|
||||
const containerPortMap = new Map();
|
||||
const hostPortMap = new Map();
|
||||
containerPortMap[runtime.params['GO_APP_PORT']] = true;
|
||||
containerPortMap[runtime.params['APP_PORT']] = true;
|
||||
hostPortMap[runtime.port] = true;
|
||||
for (const port of runtime.exposedPorts) {
|
||||
if (containerPortMap[port.containerPort]) {
|
||||
|
@ -363,6 +306,7 @@ const getRuntime = async (id: number) => {
|
|||
port: data.port,
|
||||
});
|
||||
runtime.exposedPorts = data.exposedPorts || [];
|
||||
runtime.environments = data.environments || [];
|
||||
editParams.value = data.appParams;
|
||||
searchApp(data.appID);
|
||||
open.value = true;
|
||||
|
|
|
@ -76,58 +76,8 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.appPort')" prop="params.JAVA_APP_PORT">
|
||||
<el-input v-model.number="runtime.params['JAVA_APP_PORT']" />
|
||||
<span class="input-help">{{ $t('runtime.appPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.externalPort')" prop="port">
|
||||
<el-input v-model.number="runtime.port" />
|
||||
<span class="input-help">{{ $t('runtime.externalPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('commons.button.add') + $t('commons.table.port')">
|
||||
<el-button @click="addPort">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('app.allowPort')" prop="params.HOST_IP">
|
||||
<el-switch
|
||||
v-model="runtime.params['HOST_IP']"
|
||||
:active-value="'0.0.0.0'"
|
||||
:inactive-value="'127.0.0.1'"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-for="(port, index) of runtime.exposedPorts" :key="index">
|
||||
<el-col :span="7">
|
||||
<el-form-item
|
||||
:prop="'exposedPorts.' + index + '.containerPort'"
|
||||
:rules="rules.params.JAVA_APP_PORT"
|
||||
>
|
||||
<el-input v-model.number="port.containerPort" :placeholder="$t('runtime.appPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="'exposedPorts.' + index + '.hostPort'" :rules="rules.params.JAVA_APP_PORT">
|
||||
<el-input v-model.number="port.hostPort" :placeholder="$t('runtime.externalPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="removePort(index)" link>
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<PortConfig :params="runtime.params" :exposedPorts="runtime.exposedPorts" :rules="rules" />
|
||||
<Environment :environments="runtime.environments" />
|
||||
<el-form-item :label="$t('app.containerName')" prop="params.CONTAINER_NAME">
|
||||
<el-input v-model.trim="runtime.params['CONTAINER_NAME']"></el-input>
|
||||
</el-form-item>
|
||||
|
@ -153,6 +103,8 @@ import i18n from '@/lang';
|
|||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import PortConfig from '@/views/website/runtime/port/index.vue';
|
||||
import Environment from '@/views/website/runtime/environment/index.vue';
|
||||
|
||||
interface OperateRrops {
|
||||
id?: number;
|
||||
|
@ -186,6 +138,7 @@ const initData = (type: string) => ({
|
|||
codeDir: '/',
|
||||
port: 8080,
|
||||
exposedPorts: [],
|
||||
environments: [],
|
||||
});
|
||||
let runtime = reactive<Runtime.RuntimeCreate>(initData('java'));
|
||||
const rules = ref<any>({
|
||||
|
@ -195,7 +148,6 @@ const rules = ref<any>({
|
|||
port: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
source: [Rules.requiredSelect],
|
||||
params: {
|
||||
JAVA_APP_PORT: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
HOST_IP: [Rules.requiredSelect],
|
||||
CONTAINER_NAME: [Rules.requiredInput, Rules.containerName],
|
||||
EXEC_SCRIPT: [Rules.requiredInput],
|
||||
|
@ -205,7 +157,7 @@ const scripts = ref<Runtime.NodeScripts[]>([]);
|
|||
const em = defineEmits(['close']);
|
||||
|
||||
watch(
|
||||
() => runtime.params['JAVA_APP_PORT'],
|
||||
() => runtime.params['APP_PORT'],
|
||||
(newVal) => {
|
||||
if (newVal && mode.value == 'create') {
|
||||
runtime.port = newVal;
|
||||
|
@ -234,17 +186,6 @@ const getPath = (codeDir: string) => {
|
|||
runtime.codeDir = codeDir;
|
||||
};
|
||||
|
||||
const addPort = () => {
|
||||
runtime.exposedPorts.push({
|
||||
hostPort: undefined,
|
||||
containerPort: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const removePort = (index: number) => {
|
||||
runtime.exposedPorts.splice(index, 1);
|
||||
};
|
||||
|
||||
const searchApp = (appID: number) => {
|
||||
SearchApp(appReq).then((res) => {
|
||||
apps.value = res.data.items || [];
|
||||
|
@ -304,7 +245,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||
if (runtime.exposedPorts && runtime.exposedPorts.length > 0) {
|
||||
const containerPortMap = new Map();
|
||||
const hostPortMap = new Map();
|
||||
containerPortMap[runtime.params['JAVA_APP_PORT']] = true;
|
||||
containerPortMap[runtime.params['APP_PORT']] = true;
|
||||
hostPortMap[runtime.port] = true;
|
||||
for (const port of runtime.exposedPorts) {
|
||||
if (containerPortMap[port.containerPort]) {
|
||||
|
@ -364,6 +305,7 @@ const getRuntime = async (id: number) => {
|
|||
port: data.port,
|
||||
});
|
||||
runtime.exposedPorts = data.exposedPorts || [];
|
||||
runtime.environments = data.environments || [];
|
||||
editParams.value = data.appParams;
|
||||
searchApp(data.appID);
|
||||
open.value = true;
|
||||
|
|
|
@ -103,58 +103,8 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.appPort')" prop="params.NODE_APP_PORT">
|
||||
<el-input v-model.number="runtime.params['NODE_APP_PORT']" />
|
||||
<span class="input-help">{{ $t('runtime.appPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.externalPort')" prop="port">
|
||||
<el-input v-model.number="runtime.port" />
|
||||
<span class="input-help">{{ $t('runtime.externalPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('commons.button.add') + $t('commons.table.port')">
|
||||
<el-button @click="addPort">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('app.allowPort')" prop="params.HOST_IP">
|
||||
<el-switch
|
||||
v-model="runtime.params['HOST_IP']"
|
||||
:active-value="'0.0.0.0'"
|
||||
:inactive-value="'127.0.0.1'"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-for="(port, index) of runtime.exposedPorts" :key="index">
|
||||
<el-col :span="7">
|
||||
<el-form-item
|
||||
:prop="'exposedPorts.' + index + '.containerPort'"
|
||||
:rules="rules.params.NODE_APP_PORT"
|
||||
>
|
||||
<el-input v-model.number="port.containerPort" :placeholder="$t('runtime.appPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="'exposedPorts.' + index + '.hostPort'" :rules="rules.params.NODE_APP_PORT">
|
||||
<el-input v-model.number="port.hostPort" :placeholder="$t('runtime.externalPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="removePort(index)" link>
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<PortConfig :params="runtime.params" :exposedPorts="runtime.exposedPorts" :rules="rules" />
|
||||
<Environment :environments="runtime.environments" />
|
||||
<el-form-item :label="$t('runtime.packageManager')" prop="params.PACKAGE_MANAGER">
|
||||
<el-select v-model="runtime.params['PACKAGE_MANAGER']">
|
||||
<el-option label="npm" value="npm"></el-option>
|
||||
|
@ -201,6 +151,8 @@ import i18n from '@/lang';
|
|||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import PortConfig from '@/views/website/runtime/port/index.vue';
|
||||
import Environment from '@/views/website/runtime/environment/index.vue';
|
||||
|
||||
interface OperateRrops {
|
||||
id?: number;
|
||||
|
@ -237,6 +189,7 @@ const initData = (type: string) => ({
|
|||
port: 3000,
|
||||
source: 'https://registry.npmjs.org/',
|
||||
exposedPorts: [],
|
||||
environments: [],
|
||||
});
|
||||
let runtime = reactive<Runtime.RuntimeCreate>(initData('node'));
|
||||
const rules = ref<any>({
|
||||
|
@ -246,7 +199,6 @@ const rules = ref<any>({
|
|||
port: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
source: [Rules.requiredSelect],
|
||||
params: {
|
||||
NODE_APP_PORT: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
PACKAGE_MANAGER: [Rules.requiredSelect],
|
||||
HOST_IP: [Rules.requiredSelect],
|
||||
EXEC_SCRIPT: [Rules.requiredSelect],
|
||||
|
@ -279,7 +231,7 @@ const imageSources = [
|
|||
];
|
||||
|
||||
watch(
|
||||
() => runtime.params['NODE_APP_PORT'],
|
||||
() => runtime.params['APP_PORT'],
|
||||
(newVal) => {
|
||||
if (newVal && mode.value == 'create') {
|
||||
runtime.port = newVal;
|
||||
|
@ -316,17 +268,6 @@ const changeScriptType = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const addPort = () => {
|
||||
runtime.exposedPorts.push({
|
||||
hostPort: undefined,
|
||||
containerPort: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const removePort = (index: number) => {
|
||||
runtime.exposedPorts.splice(index, 1);
|
||||
};
|
||||
|
||||
const getScripts = () => {
|
||||
GetNodeScripts({ codeDir: runtime.codeDir }).then((res) => {
|
||||
scripts.value = res.data;
|
||||
|
@ -398,7 +339,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||
if (runtime.exposedPorts && runtime.exposedPorts.length > 0) {
|
||||
const containerPortMap = new Map();
|
||||
const hostPortMap = new Map();
|
||||
containerPortMap[runtime.params['NODE_APP_PORT']] = true;
|
||||
containerPortMap[runtime.params['APP_PORT']] = true;
|
||||
hostPortMap[runtime.port] = true;
|
||||
for (const port of runtime.exposedPorts) {
|
||||
if (containerPortMap[port.containerPort]) {
|
||||
|
@ -458,6 +399,7 @@ const getRuntime = async (id: number) => {
|
|||
port: data.port,
|
||||
});
|
||||
runtime.exposedPorts = data.exposedPorts || [];
|
||||
runtime.environments = data.environments || [];
|
||||
editParams.value = data.appParams;
|
||||
searchApp(data.appID);
|
||||
if (data.params['CUSTOM_SCRIPT'] == undefined || data.params['CUSTOM_SCRIPT'] == '0') {
|
||||
|
|
80
frontend/src/views/website/runtime/port/index.vue
Normal file
80
frontend/src/views/website/runtime/port/index.vue
Normal file
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.appPort')" prop="params.APP_PORT" :rules="rules.port">
|
||||
<el-input v-model.number="params.APP_PORT" />
|
||||
<span class="input-help">{{ $t('runtime.appPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :label="$t('runtime.externalPort')" prop="params.port" :rules="rules.port">
|
||||
<el-input v-model.number="params.port" />
|
||||
<span class="input-help">{{ $t('runtime.externalPortHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('commons.button.add') + $t('commons.table.port')">
|
||||
<el-button @click="addPort">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item :label="$t('app.allowPort')">
|
||||
<el-switch v-model="params.HOST_IP" :active-value="'0.0.0.0'" :inactive-value="'127.0.0.1'" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-for="(port, index) in exposedPorts" :key="index">
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="`exposedPorts.${index}.containerPort`" :rules="rules.port">
|
||||
<el-input v-model.number="port.containerPort" :placeholder="$t('runtime.appPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item :prop="`exposedPorts.${index}.hostPort`" :rules="rules.port">
|
||||
<el-input v-model.number="port.hostPort" :placeholder="$t('runtime.externalPort')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="removePort(index)" link>
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||
import { FormRules } from 'element-plus';
|
||||
import { defineProps } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
|
||||
const props = defineProps({
|
||||
params: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
exposedPorts: {
|
||||
type: Array<Runtime.ExposedPort>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
port: [Rules.requiredInput, Rules.paramPort, checkNumberRange(1, 65535)],
|
||||
});
|
||||
|
||||
const addPort = () => {
|
||||
props.exposedPorts.push({
|
||||
hostPort: undefined,
|
||||
containerPort: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const removePort = (index: number) => {
|
||||
props.exposedPorts.splice(index, 1);
|
||||
};
|
||||
</script>
|
|
@ -49,7 +49,6 @@
|
|||
</DrawerPro>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { GetCA } from '@/api/modules/website';
|
||||
import { ref } from 'vue';
|
||||
|
||||
|
|
Loading…
Reference in a new issue