mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-12 01:24:38 +08:00
feat: Script within the container support the selection of users (#9170)
Refs #8766
This commit is contained in:
parent
692c77eb1a
commit
9f0338382f
6 changed files with 80 additions and 11 deletions
|
@ -35,6 +35,29 @@ func (b *BaseApi) SearchContainer(c *gin.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Load container users
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithName true "request"
|
||||
// @Produce json
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/users [post]
|
||||
func (b *BaseApi) LoadContainerUsers(c *gin.Context) {
|
||||
var req dto.OperationWithName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
list, err := containerService.LoadUsers(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary List containers
|
||||
// @Accept json
|
||||
|
|
|
@ -83,6 +83,8 @@ type IContainerService interface {
|
|||
ComposeUpdate(req dto.ComposeUpdate) error
|
||||
Prune(req dto.ContainerPrune) (dto.ContainerPruneReport, error)
|
||||
|
||||
LoadUsers(req dto.OperationWithName) ([]string, error)
|
||||
|
||||
StreamLogs(ctx *gin.Context, params dto.StreamLog)
|
||||
}
|
||||
|
||||
|
@ -1083,6 +1085,21 @@ func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error
|
|||
return &data, nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) LoadUsers(req dto.OperationWithName) ([]string, error) {
|
||||
std, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s cat /etc/passwd", req.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var users []string
|
||||
lines := strings.Split(string(std), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, ":") {
|
||||
users = append(users, strings.Split(line, ":")[0])
|
||||
}
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func stringsToMap(list []string) map[string]string {
|
||||
var labelMap = make(map[string]string)
|
||||
for _, label := range list {
|
||||
|
|
|
@ -118,11 +118,21 @@ func (u *CronjobService) handleShell(cronjob model.Cronjob, taskItem *task.Task)
|
|||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
|
||||
taskItem.AddSubTaskWithOps(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error {
|
||||
if len(cronjob.ContainerName) != 0 {
|
||||
scriptItem := cronjob.Script
|
||||
if cronjob.ScriptMode == "select" {
|
||||
scriptItem = path.Join("/tmp", path.Base(cronjob.Script))
|
||||
if err := cmdMgr.Run("docker", "cp", cronjob.Script, cronjob.ContainerName+":"+scriptItem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
command := "sh"
|
||||
if len(cronjob.Command) != 0 {
|
||||
command = cronjob.Command
|
||||
}
|
||||
return cmdMgr.Run("docker", "exec", cronjob.ContainerName, command, "-c", strings.ReplaceAll(cronjob.Script, "\"", "\\\""))
|
||||
if len(cronjob.User) != 0 {
|
||||
return cmdMgr.Run("docker", "exec", "-u", cronjob.User, cronjob.ContainerName, command, "-c", strings.ReplaceAll(scriptItem, "\"", "\\\""))
|
||||
}
|
||||
return cmdMgr.Run("docker", "exec", cronjob.ContainerName, command, "-c", strings.ReplaceAll(scriptItem, "\"", "\\\""))
|
||||
}
|
||||
if len(cronjob.Executor) == 0 {
|
||||
cronjob.Executor = "bash"
|
||||
|
|
|
@ -33,6 +33,8 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
|||
baRouter.POST("/operate", baseApi.ContainerOperation)
|
||||
baRouter.POST("/prune", baseApi.ContainerPrune)
|
||||
|
||||
baRouter.POST("/users", baseApi.LoadContainerUsers)
|
||||
|
||||
baRouter.GET("/repo", baseApi.ListRepo)
|
||||
baRouter.POST("/repo/status", baseApi.CheckRepoStatus)
|
||||
baRouter.POST("/repo/search", baseApi.SearchRepo)
|
||||
|
|
|
@ -9,6 +9,9 @@ export const searchContainer = (params: Container.ContainerSearch) => {
|
|||
export const listContainer = () => {
|
||||
return http.post<Array<string>>(`/containers/list`, {});
|
||||
};
|
||||
export const loadContainerUsers = (name: string) => {
|
||||
return http.post<Array<string>>(`/containers/users`, { name: name });
|
||||
};
|
||||
export const loadContainerStatus = () => {
|
||||
return http.get<Container.ContainerStatus>(`/containers/status`);
|
||||
};
|
||||
|
|
|
@ -343,7 +343,7 @@
|
|||
<el-row :gutter="20">
|
||||
<el-col :span="24" v-if="hasScript()">
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="form.inContainer">
|
||||
<el-checkbox @change="loadUserOptions(false)" v-model="form.inContainer">
|
||||
{{ $t('cronjob.containerCheckBox') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
|
@ -351,7 +351,10 @@
|
|||
<el-row :gutter="20" v-if="form.inContainer">
|
||||
<LayoutCol>
|
||||
<el-form-item :label="$t('cronjob.containerName')" prop="containerName">
|
||||
<el-select v-model="form.containerName">
|
||||
<el-select
|
||||
@change="loadUserOptions(false)"
|
||||
v-model="form.containerName"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in containerOptions"
|
||||
:key="item"
|
||||
|
@ -363,7 +366,7 @@
|
|||
</LayoutCol>
|
||||
<LayoutCol>
|
||||
<el-form-item
|
||||
:label="$t('container.command') + 123"
|
||||
:label="$t('container.command')"
|
||||
prop="command"
|
||||
:rules="Rules.requiredInput"
|
||||
>
|
||||
|
@ -390,7 +393,7 @@
|
|||
</el-form-item>
|
||||
</LayoutCol>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-if="!form.inContainer">
|
||||
<el-row :gutter="20">
|
||||
<LayoutCol>
|
||||
<el-form-item :label="$t('commons.table.user')" prop="user">
|
||||
<el-select filterable v-model="form.user">
|
||||
|
@ -400,7 +403,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</LayoutCol>
|
||||
<LayoutCol>
|
||||
<LayoutCol v-if="!form.inContainer">
|
||||
<el-form-item :label="$t('cronjob.executor')" prop="executor">
|
||||
<el-checkbox border v-model="form.isCustom">
|
||||
{{ $t('container.custom') }}
|
||||
|
@ -693,6 +696,7 @@ import {
|
|||
weekOptions,
|
||||
} from '../helper';
|
||||
import { loadUsers } from '@/api/modules/toolbox';
|
||||
import { loadContainerUsers } from '@/api/modules/container';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { GlobalStore } from '@/store';
|
||||
import LicenseImport from '@/components/license-import/index.vue';
|
||||
|
@ -784,13 +788,13 @@ const search = async () => {
|
|||
form.scriptMode = res.data.scriptMode;
|
||||
|
||||
form.containerName = res.data.containerName;
|
||||
form.user = res.data.user;
|
||||
if (form.containerName.length !== 0) {
|
||||
form.inContainer = true;
|
||||
form.command = res.data.command || 'sh';
|
||||
form.isCustom = form.command !== 'sh' && form.command !== 'bash' && form.command !== 'ash';
|
||||
} else {
|
||||
form.executor = res.data.executor || 'bash';
|
||||
form.user = res.data.user;
|
||||
form.isCustom =
|
||||
form.executor !== 'sh' &&
|
||||
form.executor !== 'bash' &&
|
||||
|
@ -846,7 +850,7 @@ const search = async () => {
|
|||
}
|
||||
loadBackups();
|
||||
loadAppInstalls();
|
||||
loadShellUsers();
|
||||
loadUserOptions(true);
|
||||
loadWebsites();
|
||||
loadContainers();
|
||||
loadScripts();
|
||||
|
@ -1205,9 +1209,19 @@ const changeAccount = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const loadShellUsers = async () => {
|
||||
const res = await loadUsers();
|
||||
userOptions.value = res.data || [];
|
||||
const loadUserOptions = async (isInit: boolean) => {
|
||||
if (!form.inContainer) {
|
||||
const res = await loadUsers();
|
||||
userOptions.value = res.data || [];
|
||||
} else {
|
||||
if (!isInit) {
|
||||
form.user = '';
|
||||
}
|
||||
if (form.containerName) {
|
||||
const res = await loadContainerUsers(form.containerName);
|
||||
userOptions.value = res.data || [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const loadAppInstalls = async () => {
|
||||
|
|
Loading…
Add table
Reference in a new issue