mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-11 09:05:51 +08:00
feat: Sync docker proxy to nodes (#8359)
This commit is contained in:
parent
0934534ac5
commit
898be9e420
11 changed files with 118 additions and 8 deletions
|
@ -33,6 +33,8 @@ const (
|
|||
|
||||
OneDriveRedirectURI = "http://localhost/login/authorized"
|
||||
GoogleRedirectURI = "http://localhost:8080"
|
||||
|
||||
DaemonJsonPath = "/etc/docker/daemon.json"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -1520,6 +1520,11 @@ const message = {
|
|||
proxyDocker: 'Docker Proxy',
|
||||
proxyDockerHelper:
|
||||
'Synchronize proxy server configuration to Docker, support offline server image pulling and other operations',
|
||||
syncToNode: 'Sync to Node',
|
||||
syncToNodeHelper: 'Sync settings to other nodes',
|
||||
nodes: 'Node',
|
||||
selectNode: 'Select Node',
|
||||
selectNodeError: 'Please select a node',
|
||||
apiInterface: 'API Interface',
|
||||
apiInterfaceClose: 'Once closed, API interfaces cannot be accessed. Do you want to continue?',
|
||||
apiInterfaceHelper: 'Provide panel support for API interface access',
|
||||
|
|
|
@ -1461,6 +1461,11 @@ const message = {
|
|||
proxyDocker: 'Dockerプロキシ',
|
||||
proxyDockerHelper:
|
||||
'プロキシサーバーの構成をDockerに同期し、オフラインサーバーイメージの引っ張りやその他の操作をサポートします',
|
||||
syncToNode: '子ノードに同期',
|
||||
syncToNodeHelper: '選択したノードへの同期設定',
|
||||
nodes: 'ノード',
|
||||
selectNode: 'ノードを選択',
|
||||
selectNodeError: 'ノードを選択してください',
|
||||
apiInterface: 'APIを有効にします',
|
||||
apiInterfaceClose: '閉じたら、APIインターフェイスにアクセスできません。続けたいですか?',
|
||||
apiInterfaceHelper: 'サードパーティのアプリケーションにAPIにアクセスできるようにします。',
|
||||
|
|
|
@ -1443,6 +1443,11 @@ const message = {
|
|||
proxyDocker: 'Docker 프록시',
|
||||
proxyDockerHelper:
|
||||
'프록시 서버 구성을 Docker 에 동기화하여 오프라인 서버 이미지 가져오기 등의 작업을 지원합니다.',
|
||||
syncToNode: '자식 노드로 동기화',
|
||||
syncToNodeHelper: '다른 노드로 설정 동기화',
|
||||
nodes: '노드',
|
||||
selectNode: '노드 선택',
|
||||
selectNodeError: '노드를 선택해 주세요',
|
||||
apiInterface: 'API 활성화',
|
||||
apiInterfaceClose: '비활성화하면 API 인터페이스에 접근할 수 없습니다. 계속하시겠습니까?',
|
||||
apiInterfaceHelper: '서드파티 애플리케이션이 API 에 접근할 수 있도록 허용합니다.',
|
||||
|
|
|
@ -1505,6 +1505,11 @@ const message = {
|
|||
proxyDocker: 'Proksi Docker',
|
||||
proxyDockerHelper:
|
||||
'Selaraskan konfigurasi pelayan proksi ke Docker, menyokong tarikan imej pelayan luar talian dan operasi lain',
|
||||
syncToNode: 'Penyegerakan ke nod anak',
|
||||
syncToNodeHelper: 'Penyegerakan tetapan ke nod lain',
|
||||
nodes: 'Nod',
|
||||
selectNode: 'Pilih nod',
|
||||
selectNodeError: 'Sila pilih nod',
|
||||
apiInterface: 'Aktifkan API',
|
||||
apiInterfaceClose: 'Setelah ditutup, antara muka API tidak boleh diakses. Adakah anda mahu meneruskan?',
|
||||
apiInterfaceHelper: 'Benarkan aplikasi pihak ketiga mengakses API.',
|
||||
|
|
|
@ -1490,6 +1490,11 @@ const message = {
|
|||
proxyDocker: 'Proxy Docker',
|
||||
proxyDockerHelper:
|
||||
'Sincronize a configuração do servidor proxy com o Docker, suportando operações de puxar imagens de servidor offline e outras',
|
||||
syncToNode: 'Sincronizar para o nó filho',
|
||||
syncToNodeHelper: 'Sincronizar de alerta para outros nós',
|
||||
nodes: 'Nós',
|
||||
selectNode: 'Selecionar nó',
|
||||
selectNodeError: 'Por favor, selecione um nó',
|
||||
apiInterface: 'Habilitar API',
|
||||
apiInterfaceClose: 'Uma vez fechado, as interfaces da API não poderão ser acessadas. Deseja continuar?',
|
||||
apiInterfaceHelper: 'Permitir que aplicativos de terceiros acessem a API.',
|
||||
|
|
|
@ -1494,6 +1494,11 @@ const message = {
|
|||
proxyDocker: 'Прокси Docker',
|
||||
proxyDockerHelper:
|
||||
'Синхронизировать конфигурацию прокси-сервера с Docker, поддержка офлайн загрузки образов и других операций',
|
||||
syncToNode: 'Синхронизация с дочерним узлом',
|
||||
syncToNodeHelper: 'Синхронизация настроек с другими узлами',
|
||||
nodes: 'Узлы',
|
||||
selectNode: 'Выберите узел',
|
||||
selectNodeError: 'Пожалуйста, выберите узел',
|
||||
apiInterface: 'Включить API',
|
||||
apiInterfaceClose: 'После закрытия API-интерфейсы будут недоступны. Хотите продолжить?',
|
||||
apiInterfaceHelper: 'Разрешить сторонним приложениям доступ к API.',
|
||||
|
|
|
@ -1439,6 +1439,11 @@ const message = {
|
|||
proxyPasswdKeep: '記住密碼',
|
||||
proxyDocker: 'Docker 代理',
|
||||
proxyDockerHelper: '將代理伺服器配寘同步至 Docker,支持離線服務器拉取鏡像等操作',
|
||||
syncToNode: '同步至子節點',
|
||||
syncToNodeHelper: '同步設置至其他節點',
|
||||
nodes: '節點',
|
||||
selectNode: '選擇節點',
|
||||
selectNodeError: '請選擇節點',
|
||||
apiInterface: 'API 接口',
|
||||
apiInterfaceClose: '關閉後將不能使用 API 接口進行訪問,是否繼續?',
|
||||
apiInterfaceHelper: '提供面板支持 API 接口訪問',
|
||||
|
|
|
@ -1435,6 +1435,11 @@ const message = {
|
|||
proxyPasswdKeep: '记住密码',
|
||||
proxyDocker: 'Docker 代理',
|
||||
proxyDockerHelper: '将代理服务器配置同步至 Docker,支持离线服务器拉取镜像等操作',
|
||||
syncToNode: '同步至子节点',
|
||||
syncToNodeHelper: '同步设置至所选节点',
|
||||
nodes: '节点',
|
||||
selectNode: '选择节点',
|
||||
selectNodeError: '请选择节点',
|
||||
apiInterface: 'API 接口',
|
||||
apiInterfaceClose: '关闭后将不能使用 API 接口进行访问,是否继续?',
|
||||
apiInterfaceHelper: '提供面板支持 API 接口访问',
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.proxy')" prop="proxyShow">
|
||||
<el-form-item :label="$t('setting.proxy')" prop="proxyShow" v-if="isMaster">
|
||||
<el-input disabled v-model="form.proxyShow">
|
||||
<template #append>
|
||||
<el-button @click="onChangeProxy" icon="Setting">
|
||||
|
@ -229,7 +229,7 @@ const loading = ref(false);
|
|||
const i18n = useI18n();
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
const { isMasterProductPro } = storeToRefs(globalStore);
|
||||
const { isMasterProductPro, isMaster } = storeToRefs(globalStore);
|
||||
|
||||
const { switchTheme } = useTheme();
|
||||
const mobile = computed(() => {
|
||||
|
@ -266,6 +266,8 @@ const form = reactive({
|
|||
proxyPasswd: '',
|
||||
proxyPasswdKeep: '',
|
||||
proxyDocker: '',
|
||||
proxyDockerSyncToNode: '',
|
||||
proxyDockerSyncNodes: '',
|
||||
|
||||
apiInterfaceStatus: 'Disable',
|
||||
apiKey: '',
|
||||
|
@ -339,6 +341,8 @@ const search = async () => {
|
|||
: '{"light":"#005eeb","dark":"#F0BE96"}';
|
||||
globalStore.themeConfig.theme = form.theme;
|
||||
form.proxyDocker = xpackRes.data.proxyDocker;
|
||||
form.proxyDockerSyncToNode = xpackRes.data.proxyDockerSyncToNode;
|
||||
form.proxyDockerSyncNodes = xpackRes.data.proxyDockerSyncNodes;
|
||||
}
|
||||
} else {
|
||||
globalStore.themeConfig.theme = form.theme;
|
||||
|
@ -369,6 +373,8 @@ const onChangeProxy = () => {
|
|||
passwd: form.proxyPasswd,
|
||||
passwdKeep: form.proxyPasswdKeep,
|
||||
proxyDocker: form.proxyDocker,
|
||||
proxyDockerSyncToNode: form.proxyDockerSyncToNode,
|
||||
proxyDockerSyncNodes: form.proxyDockerSyncNodes,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -46,9 +46,41 @@
|
|||
<el-checkbox v-model="form.proxyPasswdKeepItem" :label="$t('setting.proxyPasswdKeep')" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="isMasterProductPro">
|
||||
<el-checkbox v-model="form.proxyDocker" :label="$t('setting.proxyDocker')" />
|
||||
<el-checkbox v-model="form.proxyDocker" @change="onChange" :label="$t('setting.proxyDocker')" />
|
||||
<span class="input-help">{{ $t('setting.proxyDockerHelper') }}</span>
|
||||
</el-form-item>
|
||||
<div v-if="form.proxyDocker">
|
||||
<el-form-item prop="syncToNode">
|
||||
<el-switch
|
||||
@change="getNodes"
|
||||
v-model="form.syncToNode"
|
||||
active-value="Enable"
|
||||
inactive-value="Disable"
|
||||
></el-switch>
|
||||
<span class="ml-2.5 el-checkbox">{{ $t('setting.syncToNode') }}</span>
|
||||
<span class="input-help">{{ $t('setting.syncToNodeHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.nodes')" prop="nodes" v-if="form.syncToNode === 'Enable'">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-select v-model="form.selectNode" class="p-w-200">
|
||||
<el-option :label="$t('commons.table.all')" value="all"></el-option>
|
||||
<el-option :label="$t('setting.selectNode')" value="select"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="12" v-if="form.selectNode === 'select'">
|
||||
<el-select v-model="form.nodes" multiple class="p-w-200">
|
||||
<el-option
|
||||
v-for="item in nodeList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
@ -70,13 +102,13 @@ import i18n from '@/lang';
|
|||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { updateProxy } from '@/api/modules/setting';
|
||||
import { listNodeOptions, updateProxy } from '@/api/modules/setting';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { updateXpackSettingByKey } from '@/utils/xpack';
|
||||
import { updateDaemonJson } from '@/api/modules/container';
|
||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { escapeProxyURL } from '@/utils/util';
|
||||
import { updateDockerProxySetting } from '@/xpack/api/modules/setting';
|
||||
|
||||
const globalStore = GlobalStore();
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
@ -103,7 +135,11 @@ const form = reactive({
|
|||
proxyPasswdKeep: '',
|
||||
proxyPasswdKeepItem: false,
|
||||
proxyDocker: false,
|
||||
syncToNode: 'Enable',
|
||||
selectNode: 'all',
|
||||
nodes: [],
|
||||
});
|
||||
const nodeList = ref([]);
|
||||
|
||||
interface DialogProps {
|
||||
url: string;
|
||||
|
@ -113,6 +149,8 @@ interface DialogProps {
|
|||
passwd: string;
|
||||
passwdKeep: string;
|
||||
proxyDocker: string;
|
||||
proxyDockerSyncToNode: string;
|
||||
proxyDockerSyncNodes: string;
|
||||
}
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
if (params.url) {
|
||||
|
@ -129,11 +167,24 @@ const acceptParams = (params: DialogProps): void => {
|
|||
form.proxyUser = params.user;
|
||||
form.proxyPasswd = params.passwd;
|
||||
form.proxyDocker = params.proxyDocker !== '';
|
||||
if (form.proxyDocker) {
|
||||
getNodes();
|
||||
form.syncToNode = params.proxyDockerSyncToNode;
|
||||
form.nodes = params.proxyDockerSyncNodes ? JSON.parse(params.proxyDockerSyncNodes) : [];
|
||||
form.selectNode = form.nodes.length > 0 ? 'select' : 'all';
|
||||
}
|
||||
|
||||
proxyDockerVisible.value = params.proxyDocker !== '';
|
||||
passwordVisible.value = true;
|
||||
form.proxyPasswdKeepItem = params.passwdKeep === 'Enable';
|
||||
};
|
||||
|
||||
const getNodes = () => {
|
||||
if (form.syncToNode === 'Enable' && nodeList.value.length === 0) {
|
||||
listNodes();
|
||||
}
|
||||
};
|
||||
|
||||
const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
|
@ -216,16 +267,27 @@ const onSubmit = async () => {
|
|||
if (isClose || params.proxyDocker === false) {
|
||||
proxyUrl = '';
|
||||
}
|
||||
await updateXpackSettingByKey('ProxyDocker', proxyUrl);
|
||||
await updateDaemonJson(`${form.proxyType}-proxy`, proxyUrl);
|
||||
let param = {
|
||||
proxyDocker: proxyUrl,
|
||||
proxyDockerSyncToNode: form.syncToNode,
|
||||
proxyDockerSyncNodes: JSON.stringify(form.nodes),
|
||||
};
|
||||
await updateDockerProxySetting(param);
|
||||
emit('search');
|
||||
handleClose();
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
} catch {
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const listNodes = async () => {
|
||||
try {
|
||||
const res = await listNodeOptions();
|
||||
nodeList.value = res.data || [];
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
passwordVisible.value = false;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue