This commit is contained in:
2026-06-25 18:34:45 -05:00
parent da16e5ff56
commit 552b86c323
12 changed files with 439 additions and 125 deletions

View File

@@ -243,7 +243,7 @@ const activeStatus = computed(() => {
return {
name: connection?.name || 'Selected VMware connection',
typeLabel: connection?.targetType === 'host' ? 'ESXi host' : 'vCenter',
configured: Boolean(connection?.baseUrl && connection?.username),
configured: Boolean(connection?.baseUrl && (connection?.credentialId || connection?.username)),
baseUrl: connection?.baseUrl || ''
};
}

View File

@@ -14,7 +14,7 @@
<div class="intune-config-grid">
<section class="publisher-card">
<strong>Inventory sources</strong>
<p>vCenter entries import VM inventory and power-state checks. Standalone host entries validate direct ESXi connections through the vSphere Web Services API.</p>
<p>vCenter and standalone ESXi entries use Credential Vault entries for VMware API authentication, inventory import, and power-state checks.</p>
<div class="config-stat-row">
<span><b>{{ connections.length }}</b><small>systems</small></span>
<span><b>{{ enabledCount }}</b><small>enabled</small></span>
@@ -28,7 +28,7 @@
<strong>VMware systems</strong>
<div v-for="connection in connections" :key="connection.id" class="check-row">
<b>{{ connection.name }}</b>
<small>{{ connection.baseUrl }} - {{ connectionTypeLabel(connection) }} - {{ connection.apiMode }} - {{ connection.lastTestStatus || 'untested' }}</small>
<small>{{ connection.baseUrl }} - {{ connectionTypeLabel(connection) }} - {{ connection.credentialName || connection.username || 'No vault credential' }} - {{ connection.lastTestStatus || 'untested' }}</small>
<span>
<button class="ghost-button compact" type="button" @click="openModal(connection)">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i>Edit
@@ -49,7 +49,7 @@
:open="modalOpen"
:title="form.id ? 'Update VMware connection' : 'New VMware connection'"
eyebrow="CONFIG / VMWARE"
description="Store VMware credentials encrypted at rest. vCenter systems can import VM inventory; standalone hosts use the vSphere Web Services API for direct connection validation."
description="Select a Credential Vault username/password entry for VMware API authentication. vCenter systems and standalone ESXi hosts both use the selected vault credential."
wide
@close="modalOpen = false"
>
@@ -63,8 +63,16 @@
</label>
<label><span>Name</span><input v-model="form.name" required :placeholder="form.targetType === 'host' ? 'Rack ESXi host 01' : 'Production vCenter'" /></label>
<label><span>Base URL</span><input v-model="form.baseUrl" required :placeholder="baseUrlPlaceholder" /></label>
<label><span>Username</span><input v-model="form.username" required :placeholder="form.targetType === 'host' ? 'root or delegated ESXi account' : 'administrator@vsphere.local'" /></label>
<label><span>{{ form.id ? 'Replace password' : 'Password' }}</span><input v-model="form.password" :required="!form.id" type="password" placeholder="Stored encrypted after save" /></label>
<label class="full">
<span>Credential Vault entry</span>
<select v-model="form.credentialId" required>
<option value="" disabled>Choose VMware API credential</option>
<option v-for="credential in vmwareCredentials" :key="credential.id" :value="credential.id">
{{ credential.name }}{{ credential.username ? ` - ${credential.username}` : '' }}
</option>
</select>
<small>Use a username/password credential. Create or update secrets in Credential Vault.</small>
</label>
<label>
<span>API mode</span>
<select v-model="form.apiMode" :disabled="form.targetType === 'host'">
@@ -98,7 +106,8 @@ import BaseModal from '../ui/BaseModal.vue';
const props = defineProps({
connections: { type: Array, default: () => [] },
groups: { type: Array, default: () => [] }
groups: { type: Array, default: () => [] },
credentials: { type: Array, default: () => [] }
});
const emit = defineEmits(['save', 'delete', 'test']);
@@ -109,6 +118,7 @@ const enabledCount = computed(() => props.connections.filter((connection) => con
const vcenterCount = computed(() => props.connections.filter((connection) => connection.targetType !== 'host').length);
const standaloneCount = computed(() => props.connections.filter((connection) => connection.targetType === 'host').length);
const testedCount = computed(() => props.connections.filter((connection) => connection.lastTestStatus).length);
const vmwareCredentials = computed(() => props.credentials.filter((credential) => credential.kind === 'username_password'));
const baseUrlPlaceholder = computed(() => form.targetType === 'host' ? 'https://esxi01.contoso.local' : 'https://vcenter.contoso.local');
const enabledHelpText = computed(() => form.targetType === 'host'
? 'Allow this standalone host connection to be tested and used for direct VMware host workflows.'
@@ -128,8 +138,7 @@ function defaultForm() {
name: '',
targetType: 'vcenter',
baseUrl: '',
username: '',
password: '',
credentialId: '',
apiMode: 'auto',
requestTimeoutMs: 20000,
allowUntrustedTls: false,
@@ -143,7 +152,7 @@ function openModal(connection = null) {
Object.assign(form, defaultForm(), connection || {});
form.targetType = connection?.targetType || 'vcenter';
form.apiMode = form.targetType === 'host' ? 'web-services' : (connection?.apiMode || 'auto');
form.password = '';
form.credentialId = connection?.credentialId || '';
form.groupId = connection?.groupId || '';
modalOpen.value = true;
}