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