Pulse/internal/vmware/provider_test.go
rcourtman 5016cbc2ba Add vSphere network inventory
Project vCenter network inventory through canonical resources and add the vSphere Networks table backed by vCenter network topology. Align resource presentation coalescing so state and resource APIs share the same host contract.
2026-05-22 20:26:56 +01:00

562 lines
23 KiB
Go

package vmware
import (
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
)
func TestProviderRecords_ProjectCanonicalVMwareResources(t *testing.T) {
previous := IsFeatureEnabled()
SetFeatureEnabled(true)
t.Cleanup(func() { SetFeatureEnabled(previous) })
collectedAt := time.Date(2026, time.March, 30, 18, 15, 0, 0, time.UTC)
provider := NewProvider(InventorySnapshot{
ConnectionID: "vc-1",
ConnectionName: "Lab VC",
VCenterHost: "vc.lab.local",
CollectedAt: collectedAt,
Hosts: []InventoryHost{{
Host: "host-101",
Name: "esxi-01.lab.local",
ConnectionState: "CONNECTED",
PowerState: "POWERED_ON",
HostUUID: "uuid-host-1",
DatacenterID: "datacenter-1",
DatacenterName: "DC1",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Prod Compute",
ClusterID: "domain-c101",
ClusterName: "Prod Compute",
ClusterHAEnabled: boolPtr(true),
ClusterDRSEnabled: boolPtr(false),
FolderID: "group-h4",
FolderName: "Prod Hosts",
DatastoreIDs: []string{"datastore-11"},
DatastoreNames: []string{"nvme-primary"},
OverallStatus: "yellow",
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(21.4),
MemoryPercent: float64Ptr(63.2),
MemoryUsedBytes: int64Ptr(27144105984),
MemoryTotalBytes: int64Ptr(42949672960),
NetInBytesPerSecond: float64Ptr(1024),
NetOutBytesPerSecond: float64Ptr(2048),
DiskReadBytesPerSecond: float64Ptr(4096),
DiskWriteBytesPerSecond: float64Ptr(8192),
},
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-11",
Name: "Host connection degraded",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-2 * time.Minute),
}},
RecentTasks: []InventoryTask{{
Task: "task-11",
Name: "Reconnect host",
State: "running",
StartedAt: collectedAt.Add(-1 * time.Minute),
}},
}},
VMs: []InventoryVM{{
VM: "vm-201",
Name: "app-01",
PowerState: "POWERED_ON",
CPUCount: 4,
MemorySizeMiB: 8192,
DatacenterID: "datacenter-1",
DatacenterName: "DC1",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Prod Compute",
ClusterID: "domain-c101",
ClusterName: "Prod Compute",
ClusterHAEnabled: boolPtr(true),
ClusterDRSEnabled: boolPtr(false),
FolderID: "group-v7",
FolderName: "Production VMs",
ResourcePoolID: "resgroup-22",
ResourcePoolName: "Tier 1",
RuntimeHostID: "host-101",
RuntimeHostName: "esxi-01.lab.local",
DatastoreIDs: []string{"datastore-11"},
DatastoreNames: []string{"nvme-primary"},
InstanceUUID: "vm-instance-201",
BIOSUUID: "vm-bios-201",
GuestOSFamily: "LINUX",
GuestHostname: "app-01.internal",
GuestIPAddresses: []string{"10.0.0.21"},
OverallStatus: "green",
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(38.1),
MemoryPercent: float64Ptr(57.5),
MemoryUsedBytes: int64Ptr(5033164800),
MemoryTotalBytes: int64Ptr(8589934592),
NetInBytesPerSecond: float64Ptr(512),
NetOutBytesPerSecond: float64Ptr(768),
DiskReadBytesPerSecond: float64Ptr(1536),
DiskWriteBytesPerSecond: float64Ptr(2048),
},
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-21",
Name: "VM replication fault",
OverallStatus: "red",
TriggeredAt: collectedAt.Add(-3 * time.Minute),
}},
RecentTasks: []InventoryTask{{
Task: "task-21",
Name: "Create snapshot",
State: "success",
StartedAt: collectedAt.Add(-5 * time.Minute),
}},
SnapshotCount: 2,
CurrentSnapshotID: "snapshot-202",
SnapshotTree: []InventoryVMSnapshot{{
Snapshot: "snapshot-201",
Name: "pre-upgrade",
Description: "Before application upgrade",
ID: 101,
CreatedAt: timePtr(collectedAt.Add(-48 * time.Hour)),
State: "poweredOn",
Quiesced: true,
Children: []InventoryVMSnapshot{{
Snapshot: "snapshot-202",
Name: "post-migration-checkpoint",
ID: 102,
CreatedAt: timePtr(collectedAt.Add(-24 * time.Hour)),
State: "poweredOn",
Current: true,
}},
}},
NetworkAdapters: []InventoryVMNetworkAdapter{{
NIC: "4000",
Label: "Network adapter 1",
Type: "VMXNET3",
MACType: "GENERATED",
MACAddress: "00:50:56:aa:bb:cc",
PCISlotNumber: int64Ptr(160),
BackingType: "STANDARD_PORTGROUP",
NetworkID: "network-101",
NetworkName: "VM Network",
DistributedSwitchUUID: "50 2b d1",
State: "CONNECTED",
StartConnected: true,
AllowGuestControl: true,
WakeOnLANEnabled: true,
}},
VirtualDisks: []InventoryVMVirtualDisk{{
Disk: "2000",
Label: "Hard disk 1",
Type: "SCSI",
SCSIBus: int64Ptr(0),
SCSIUnit: int64Ptr(1),
BackingType: "VMDK_FILE",
VMDKFile: "[nvme-primary] app-01/app-01.vmdk",
DatastoreName: "nvme-primary",
CapacityBytes: int64Ptr(107374182400),
}},
Tools: &InventoryVMTools{
AutoUpdateSupported: boolPtr(true),
InstallAttemptCount: int64Ptr(1),
VersionNumber: int64Ptr(12352),
Version: "12.4.0",
UpgradePolicy: "MANUAL",
VersionStatus: "CURRENT",
InstallType: "OPEN_VM_TOOLS",
RunState: "RUNNING",
GuestRebootRequested: boolPtr(true),
GuestRebootComponents: []string{"drivers"},
GuestRebootRequestTime: "2026-03-30T18:20:00Z",
},
Hardware: &InventoryVMHardware{
GuestOS: "UBUNTU_64",
InstantCloneFrozen: boolPtr(false),
Version: "VMX_20",
UpgradePolicy: "AFTER_CLEAN_SHUTDOWN",
UpgradeVersion: "VMX_21",
UpgradeStatus: "PENDING",
BootType: "EFI",
EFILegacyBoot: boolPtr(false),
BootNetworkProtocol: "IPV4",
BootDelayMilliseconds: int64Ptr(5000),
BootRetry: boolPtr(true),
BootRetryDelayMilliseconds: int64Ptr(10000),
EnterSetupMode: boolPtr(false),
BootDevices: []InventoryVMBootDevice{
{Type: "DISK", Disks: []string{"2000"}},
{Type: "ETHERNET", NIC: "4000"},
},
CPUCoresPerSocket: int64Ptr(2),
CPUHotAddEnabled: boolPtr(true),
CPUHotRemoveEnabled: boolPtr(false),
MemoryHotAddEnabled: boolPtr(true),
MemoryHotAddIncrementMiB: int64Ptr(256),
MemoryHotAddLimitMiB: int64Ptr(16384),
},
}},
Datastores: []InventoryDatastore{{
Datastore: "datastore-11",
Name: "nvme-primary",
Type: "VMFS",
FreeSpace: 40,
Capacity: 100,
DatacenterID: "datacenter-1",
DatacenterName: "DC1",
FolderID: "group-s4",
FolderName: "Shared Datastores",
HostIDs: []string{"host-101"},
HostNames: []string{"esxi-01.lab.local"},
VMIDs: []string{"vm-201"},
VMNames: []string{"app-01"},
Accessible: boolPtr(true),
MultipleHostAccess: boolPtr(true),
MaintenanceMode: "normal",
URL: "ds:///vmfs/volumes/datastore-11/",
OverallStatus: "yellow",
RecentTasks: []InventoryTask{{
Task: "task-31",
Name: "Refresh datastore",
State: "queued",
StartedAt: collectedAt.Add(-4 * time.Minute),
}},
}},
Networks: []InventoryNetwork{{
Network: "network-101",
Name: "VM Network",
Type: "STANDARD_PORTGROUP",
DatacenterID: "datacenter-1",
DatacenterName: "DC1",
FolderID: "group-n4",
FolderName: "Networks",
HostIDs: []string{"host-101"},
HostNames: []string{"esxi-01.lab.local"},
VMIDs: []string{"vm-201"},
VMNames: []string{"app-01"},
OverallStatus: "yellow",
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-41",
Name: "Network uplink redundancy",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-6 * time.Minute),
}},
}},
})
records := provider.Records()
if len(records) != 4 {
t.Fatalf("expected 4 VMware records, got %d", len(records))
}
hostRecord := records[0]
if hostRecord.SourceID != "vc-1:host:host-101" {
t.Fatalf("host source id = %q, want vc-1:host:host-101", hostRecord.SourceID)
}
if hostRecord.Resource.Type != unifiedresources.ResourceTypeAgent {
t.Fatalf("host resource type = %q, want %q", hostRecord.Resource.Type, unifiedresources.ResourceTypeAgent)
}
if hostRecord.Resource.Status != unifiedresources.StatusWarning {
t.Fatalf("host status = %q, want %q", hostRecord.Resource.Status, unifiedresources.StatusWarning)
}
if hostRecord.Resource.VMware == nil || hostRecord.Resource.VMware.ManagedObjectID != "host-101" {
t.Fatalf("expected VMware host metadata, got %+v", hostRecord.Resource.VMware)
}
if got := hostRecord.Resource.VMware.ActiveAlarmCount; got != 1 {
t.Fatalf("host active alarm count = %d, want 1", got)
}
if got := hostRecord.Resource.VMware.RecentTaskSummary; got != "Reconnect host (running)" {
t.Fatalf("host recent task summary = %q, want %q", got, "Reconnect host (running)")
}
if got := hostRecord.Resource.VMware.ClusterName; got != "Prod Compute" {
t.Fatalf("host cluster name = %q, want Prod Compute", got)
}
if got := hostRecord.Resource.VMware.ClusterHAEnabled; got == nil || !*got {
t.Fatalf("host cluster HA enabled = %+v, want true", got)
}
if got := hostRecord.Resource.VMware.ClusterDRSEnabled; got == nil || *got {
t.Fatalf("host cluster DRS enabled = %+v, want false", got)
}
if got := hostRecord.Resource.VMware.DatastoreNames; len(got) != 1 || got[0] != "nvme-primary" {
t.Fatalf("host datastore names = %#v, want [nvme-primary]", got)
}
if hostRecord.Resource.Metrics == nil || hostRecord.Resource.Metrics.CPU == nil || hostRecord.Resource.Metrics.Memory == nil {
t.Fatalf("expected VMware host metrics, got %+v", hostRecord.Resource.Metrics)
}
if got := hostRecord.Resource.Metrics.CPU.Percent; got != 21.4 {
t.Fatalf("host cpu percent = %v, want 21.4", got)
}
if got := hostRecord.Resource.Metrics.NetOut.Value; got != 2048 {
t.Fatalf("host net out = %v, want 2048", got)
}
if len(hostRecord.Resource.Incidents) != 1 || hostRecord.Resource.Incidents[0].Code != "vmware_alarm_state" {
t.Fatalf("expected host VMware incident projection, got %+v", hostRecord.Resource.Incidents)
}
if hostRecord.Identity.DMIUUID != "uuid-host-1" {
t.Fatalf("host identity DMI UUID = %q, want uuid-host-1", hostRecord.Identity.DMIUUID)
}
if got := hostRecord.Identity.ClusterName; got != "Prod Compute" {
t.Fatalf("host cluster name = %q, want Prod Compute", got)
}
if hostRecord.Resource.LastSeen != collectedAt {
t.Fatalf("host last seen = %v, want %v", hostRecord.Resource.LastSeen, collectedAt)
}
vmRecord := records[1]
if vmRecord.SourceID != "vc-1:vm:vm-201" {
t.Fatalf("vm source id = %q, want vc-1:vm:vm-201", vmRecord.SourceID)
}
if vmRecord.Resource.Type != unifiedresources.ResourceTypeVM {
t.Fatalf("vm resource type = %q, want %q", vmRecord.Resource.Type, unifiedresources.ResourceTypeVM)
}
if vmRecord.Resource.VMware == nil || vmRecord.Resource.VMware.CPUCount != 4 {
t.Fatalf("expected VMware VM metadata with cpu count, got %+v", vmRecord.Resource.VMware)
}
if vmRecord.Resource.Status != unifiedresources.StatusWarning {
t.Fatalf("vm status = %q, want %q", vmRecord.Resource.Status, unifiedresources.StatusWarning)
}
if got := vmRecord.Resource.VMware.ActiveAlarmSummary; got != "VM replication fault (red)" {
t.Fatalf("vm active alarm summary = %q, want %q", got, "VM replication fault (red)")
}
if got := vmRecord.Resource.VMware.ClusterHAEnabled; got == nil || !*got {
t.Fatalf("vm cluster HA enabled = %+v, want true", got)
}
if got := vmRecord.Resource.VMware.ClusterDRSEnabled; got == nil || *got {
t.Fatalf("vm cluster DRS enabled = %+v, want false", got)
}
if got := vmRecord.Resource.VMware.SnapshotCount; got != 2 {
t.Fatalf("vm snapshot count = %d, want 2", got)
}
if got := vmRecord.Resource.VMware.CurrentSnapshotID; got != "snapshot-202" {
t.Fatalf("vm current snapshot id = %q, want snapshot-202", got)
}
if got := vmRecord.Resource.VMware.SnapshotTree; len(got) != 1 || got[0].Name != "pre-upgrade" || len(got[0].Children) != 1 || !got[0].Children[0].Current {
t.Fatalf("vm snapshot tree projection = %+v, want root pre-upgrade with current child", got)
}
if got := vmRecord.Resource.VMware.NetworkAdapters; len(got) != 1 || got[0].NetworkName != "VM Network" || got[0].MACAddress != "00:50:56:aa:bb:cc" {
t.Fatalf("vm network adapter projection = %+v, want VM Network adapter with MAC", got)
}
if got := vmRecord.Resource.VMware.NetworkAdapters[0].PCISlotNumber; got == nil || *got != 160 {
t.Fatalf("vm network adapter pci slot = %+v, want 160", got)
}
if got := vmRecord.Resource.VMware.VirtualDisks; len(got) != 1 || got[0].Label != "Hard disk 1" || got[0].VMDKFile != "[nvme-primary] app-01/app-01.vmdk" {
t.Fatalf("vm virtual disk projection = %+v, want hard disk backing on nvme-primary", got)
}
if got := vmRecord.Resource.VMware.VirtualDisks[0].SCSIUnit; got == nil || *got != 1 {
t.Fatalf("vm virtual disk scsi unit = %+v, want 1", got)
}
if got := vmRecord.Resource.VMware.VirtualDisks[0].CapacityBytes; got == nil || *got != 107374182400 {
t.Fatalf("vm virtual disk capacity = %+v, want 107374182400", got)
}
if got := vmRecord.Resource.VMware.Tools; got == nil || got.RunState != "RUNNING" || got.VersionStatus != "CURRENT" || got.Version != "12.4.0" {
t.Fatalf("vm tools projection = %+v, want running/current 12.4.0", got)
}
if got := vmRecord.Resource.VMware.Tools.GuestRebootRequested; got == nil || !*got {
t.Fatalf("vm tools guest reboot requested = %+v, want true", got)
}
if got := vmRecord.Resource.VMware.Tools.GuestRebootComponents; len(got) != 1 || got[0] != "drivers" {
t.Fatalf("vm tools reboot components = %+v, want [drivers]", got)
}
if got := vmRecord.Resource.VMware.Hardware; got == nil || got.Version != "VMX_20" || got.UpgradeStatus != "PENDING" {
t.Fatalf("vm hardware projection = %+v, want VMX_20 pending", got)
}
if got := vmRecord.Resource.VMware.Hardware.BootDevices; len(got) != 2 || got[0].Disks[0] != "2000" || got[1].NIC != "4000" {
t.Fatalf("vm hardware boot devices = %+v, want disk and ethernet entries", got)
}
if got := vmRecord.Resource.VMware.Hardware.MemoryHotAddLimitMiB; got == nil || *got != 16384 {
t.Fatalf("vm hardware memory hot-add limit = %+v, want 16384", got)
}
if got := vmRecord.Resource.ParentName; got != "esxi-01.lab.local" {
t.Fatalf("vm parent name = %q, want esxi-01.lab.local", got)
}
if got := vmRecord.ParentSourceID; got != "vc-1:host:host-101" {
t.Fatalf("vm parent source id = %q, want vc-1:host:host-101", got)
}
if got := vmRecord.Resource.VMware.RuntimeHostName; got != "esxi-01.lab.local" {
t.Fatalf("vm runtime host name = %q, want esxi-01.lab.local", got)
}
if got := vmRecord.Resource.VMware.InstanceUUID; got != "vm-instance-201" {
t.Fatalf("vm instance uuid = %q, want vm-instance-201", got)
}
if got := vmRecord.Identity.MachineID; got != "vm-instance-201" {
t.Fatalf("vm machine id = %q, want vm-instance-201", got)
}
if got := vmRecord.Identity.IPAddresses; len(got) != 1 || got[0] != "10.0.0.21" {
t.Fatalf("vm identity IPs = %#v, want [10.0.0.21]", got)
}
if got := vmRecord.Identity.MACAddresses; len(got) != 1 || got[0] != "00:50:56:aa:bb:cc" {
t.Fatalf("vm identity MACs = %#v, want [00:50:56:aa:bb:cc]", got)
}
if vmRecord.Resource.Metrics == nil || vmRecord.Resource.Metrics.CPU == nil || vmRecord.Resource.Metrics.Memory == nil {
t.Fatalf("expected VMware VM metrics, got %+v", vmRecord.Resource.Metrics)
}
if got := vmRecord.Resource.Metrics.Memory.Percent; got != 57.5 {
t.Fatalf("vm memory percent = %v, want 57.5", got)
}
if got := vmRecord.Resource.Metrics.DiskWrite.Value; got != 2048 {
t.Fatalf("vm disk write = %v, want 2048", got)
}
if len(vmRecord.Resource.Incidents) != 1 || vmRecord.Resource.Incidents[0].Code != "vmware_alarm_state" {
t.Fatalf("expected VMware VM incident projection, got %+v", vmRecord.Resource.Incidents)
}
datastoreRecord := records[2]
if datastoreRecord.SourceID != "vc-1:datastore:datastore-11" {
t.Fatalf("datastore source id = %q, want vc-1:datastore:datastore-11", datastoreRecord.SourceID)
}
if datastoreRecord.Resource.Type != unifiedresources.ResourceTypeStorage {
t.Fatalf("datastore resource type = %q, want %q", datastoreRecord.Resource.Type, unifiedresources.ResourceTypeStorage)
}
if datastoreRecord.Resource.Storage == nil || datastoreRecord.Resource.Storage.Platform != "vmware-vsphere" {
t.Fatalf("expected canonical VMware storage metadata, got %+v", datastoreRecord.Resource.Storage)
}
if datastoreRecord.Resource.Status != unifiedresources.StatusWarning {
t.Fatalf("datastore status = %q, want %q", datastoreRecord.Resource.Status, unifiedresources.StatusWarning)
}
if datastoreRecord.Resource.Metrics == nil || datastoreRecord.Resource.Metrics.Disk == nil {
t.Fatal("expected datastore disk metrics to be populated")
}
if got := datastoreRecord.Resource.Metrics.Disk.Percent; got != 60 {
t.Fatalf("datastore disk usage percent = %v, want 60", got)
}
if len(datastoreRecord.Resource.Incidents) != 1 || datastoreRecord.Resource.Incidents[0].Code != "vmware_health_state" {
t.Fatalf("expected VMware datastore health incident, got %+v", datastoreRecord.Resource.Incidents)
}
if got := datastoreRecord.Resource.VMware.RecentTaskSummary; got != "Refresh datastore (queued)" {
t.Fatalf("datastore recent task summary = %q, want %q", got, "Refresh datastore (queued)")
}
if !datastoreRecord.Resource.Storage.Shared {
t.Fatal("expected datastore storage meta to mark the datastore as shared")
}
if got := datastoreRecord.Resource.Storage.Nodes; len(got) != 1 || got[0] != "esxi-01.lab.local" {
t.Fatalf("datastore storage nodes = %#v, want [esxi-01.lab.local]", got)
}
if got := datastoreRecord.Resource.Storage.ConsumerCount; got != 1 {
t.Fatalf("datastore consumer count = %d, want 1", got)
}
if got := datastoreRecord.Resource.Storage.TopConsumers; len(got) != 1 || got[0].Name != "app-01" {
t.Fatalf("datastore top consumers = %#v, want app-01", got)
}
if datastoreRecord.Resource.VMware.DatastoreAccessible == nil || !*datastoreRecord.Resource.VMware.DatastoreAccessible {
t.Fatalf("datastore accessible = %#v, want true", datastoreRecord.Resource.VMware.DatastoreAccessible)
}
networkRecord := records[3]
if networkRecord.SourceID != "vc-1:network:network-101" {
t.Fatalf("network source id = %q, want vc-1:network:network-101", networkRecord.SourceID)
}
if networkRecord.Resource.Type != unifiedresources.ResourceTypeNetwork {
t.Fatalf("network resource type = %q, want %q", networkRecord.Resource.Type, unifiedresources.ResourceTypeNetwork)
}
if networkRecord.Resource.Status != unifiedresources.StatusWarning {
t.Fatalf("network status = %q, want %q", networkRecord.Resource.Status, unifiedresources.StatusWarning)
}
if networkRecord.Resource.VMware == nil || networkRecord.Resource.VMware.NetworkType != "STANDARD_PORTGROUP" {
t.Fatalf("expected VMware network metadata, got %+v", networkRecord.Resource.VMware)
}
if got := networkRecord.Resource.VMware.NetworkHostNames; len(got) != 1 || got[0] != "esxi-01.lab.local" {
t.Fatalf("network host names = %#v, want [esxi-01.lab.local]", got)
}
if got := networkRecord.Resource.VMware.NetworkVMNames; len(got) != 1 || got[0] != "app-01" {
t.Fatalf("network VM names = %#v, want [app-01]", got)
}
if len(networkRecord.Resource.Incidents) != 1 || networkRecord.Resource.Incidents[0].Code != "vmware_alarm_state" {
t.Fatalf("expected VMware network incident projection, got %+v", networkRecord.Resource.Incidents)
}
}
func TestProviderActivityChanges_ProjectCanonicalTimelineEntries(t *testing.T) {
previous := IsFeatureEnabled()
SetFeatureEnabled(true)
t.Cleanup(func() { SetFeatureEnabled(previous) })
collectedAt := time.Date(2026, time.March, 30, 18, 20, 0, 0, time.UTC)
provider := NewProvider(InventorySnapshot{
ConnectionID: "vc-1",
ConnectionName: "Lab VC",
VCenterHost: "vc.lab.local",
CollectedAt: collectedAt,
Hosts: []InventoryHost{{
Host: "host-101",
Name: "esxi-01.lab.local",
RecentTasks: []InventoryTask{{
Task: "task-11",
Name: "Reconnect host",
State: "running",
StartedAt: collectedAt.Add(-1 * time.Minute),
}},
}},
VMs: []InventoryVM{{
VM: "vm-201",
Name: "app-01",
RecentEvents: []InventoryEvent{{
Event: "event-201",
Type: "VmMessageEvent",
Message: "Snapshot completed successfully",
User: "vpxuser",
CreatedAt: collectedAt.Add(-2 * time.Minute),
}},
}},
Datastores: []InventoryDatastore{{
Datastore: "datastore-11",
Name: "nvme-primary",
RecentEvents: []InventoryEvent{{
Event: "event-301",
Type: "DatastoreRenamedEvent",
Message: "Datastore metadata refreshed",
User: "storage-admin",
CreatedAt: collectedAt.Add(-3 * time.Minute),
}},
}},
Networks: []InventoryNetwork{{
Network: "network-101",
Name: "VM Network",
RecentEvents: []InventoryEvent{{
Event: "event-401",
Type: "NetworkEvent",
Message: "Network metadata refreshed",
User: "network-admin",
CreatedAt: collectedAt.Add(-4 * time.Minute),
}},
}},
})
changes := provider.ActivityChanges()
if len(changes) != 4 {
t.Fatalf("expected 4 VMware activity changes, got %d", len(changes))
}
if changes[0].Kind != unifiedresources.ChangeActivity {
t.Fatalf("latest change kind = %q, want %q", changes[0].Kind, unifiedresources.ChangeActivity)
}
if changes[0].SourceType != unifiedresources.SourcePlatformEvent {
t.Fatalf("latest change source type = %q, want %q", changes[0].SourceType, unifiedresources.SourcePlatformEvent)
}
if changes[0].SourceAdapter != unifiedresources.AdapterVMware {
t.Fatalf("latest change source adapter = %q, want %q", changes[0].SourceAdapter, unifiedresources.AdapterVMware)
}
if changes[0].ResourceID != "vc-1:host:host-101" {
t.Fatalf("latest change resource ID = %q, want vc-1:host:host-101", changes[0].ResourceID)
}
if changes[0].OccurredAt == nil || !changes[0].OccurredAt.Equal(collectedAt.Add(-1*time.Minute)) {
t.Fatalf("latest change occurred_at = %v, want %v", changes[0].OccurredAt, collectedAt.Add(-1*time.Minute))
}
if got := changes[0].Metadata[unifiedresources.MetadataActivityType]; got != "vmware_task" {
t.Fatalf("latest change activity_type = %#v, want vmware_task", got)
}
if got := changes[1].Metadata["vmwareEventType"]; got != "VmMessageEvent" {
t.Fatalf("vm change event type = %#v, want VmMessageEvent", got)
}
if got := changes[2].Metadata["vmwareEventUser"]; got != "storage-admin" {
t.Fatalf("datastore change user = %#v, want storage-admin", got)
}
if got := changes[3].Metadata["vmwareEntityType"]; got != "network" {
t.Fatalf("network change entity type = %#v, want network", got)
}
}
func boolPtr(value bool) *bool {
return &value
}
func timePtr(value time.Time) *time.Time {
return &value
}