Skip to content

Commit

Permalink
Added ObjectName to OutboundEvent
Browse files Browse the repository at this point in the history
In certain cases the ManagedObjectReference alone might not be useful,
e.g. when an object is deleted.

This commit adds a new field `objectName` to the outbound JSON data
which serves as additional metadata for the receiver.

Note: ObjectName for certain vSphere objects, e.g. virtual machines, is
only unique within a folder (if applicable) as per the description
[here](https://docs.vmware.com/en/VMware-vSphere/6.7/com.vmware.vsphere.vm_admin.doc/GUID-76E73C62-A973-4839-BB67-AC1817908E6D.html).

This added field should be treated as metadata and not for requests
against vCenter (use `ManagedObjectReference` instead).

Signed-off-by: Michael Gasch <[email protected]>
  • Loading branch information
embano1 authored and alexellis committed May 24, 2019
1 parent d6be2bd commit 92d133a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 28 deletions.
15 changes: 12 additions & 3 deletions pkg/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ import (
// OutboundEvent is the JSON object sent to subscribed functions
// If the ManagedObjectReference for an event cannot be retrieved, it will be nil and thus not marshaled into the JSON OutboundEvent
// It's the receivers responsibility to check whether managedObjectReference key is present in the JSON message payload
// ObjectName is the name of the object as it appears in vCenter - uniqueness is only guaranteed at the folder level, if applicable, where this object resides
type OutboundEvent struct {
Topic string `json:"topic,omitempty"`
Category string `json:"category,omitempty"`

UserName string `json:"userName,omitempty"`
CreatedTime time.Time `json:"createdTime,omitempty"`
ObjectName string `json:"objectName,omitempty"`
ManagedObjectReference *vtypes.ManagedObjectReference `json:"managedObjectReference,omitempty"`
}

Expand Down Expand Up @@ -103,13 +105,14 @@ func handleEvent(event vtypes.BaseEvent, m *event.Manager) (string, string, erro

// Get the ManagedObjectReference by converting the event into a concrete event
// If we don't find a MoRef in the event, *ref will be nil and not marshaled in the OutboundEvent making it easy for the subscribed function to validate the JSON payload
ref := getMoref(event)
name, ref := getObjectNameAndMoref(event)

message, err := json.Marshal(OutboundEvent{
Topic: topic,
Category: category,
UserName: user,
CreatedTime: createdTime,
ObjectName: name,
ManagedObjectReference: ref,
})
if err != nil {
Expand All @@ -123,10 +126,11 @@ func handleEvent(event vtypes.BaseEvent, m *event.Manager) (string, string, erro
// getMoref extracts the ManagedObjectReference, if any, by converting the BaseEvent to a concrete event
// Details on the ManagedObjectReference:
// https://code.vmware.com/docs/7371/vmware-vsphere-web-services-sdk-programming-guide-6-7-update-1#/doc/GUID-C9E81F17-2516-49EE-914F-EE9904258ED3.html
func getMoref(event vtypes.BaseEvent) *vtypes.ManagedObjectReference {
func getObjectNameAndMoref(event vtypes.BaseEvent) (string, *vtypes.ManagedObjectReference) {
// This pointer to the ManagedObjectReference will be used during the BaseEvent switch below
// If we don't find a MoRef in the event, *ref will be nil and not marshaled in the OutboundEvent
var ref *vtypes.ManagedObjectReference
var objName string

// Get the underlying concrete base event, e.g. VmEvent
// vSphere Web Service API Reference 6.7
Expand All @@ -135,30 +139,35 @@ func getMoref(event vtypes.BaseEvent) *vtypes.ManagedObjectReference {
// Alerts
case vtypes.BaseAlarmEvent:
e := baseEvent.GetAlarmEvent()
objName = e.Alarm.Name
ref = &e.Alarm.Alarm

// Datastore
case vtypes.BaseDatastoreEvent:
e := baseEvent.GetDatastoreEvent()
objName = e.Datastore.Name
ref = &e.Datastore.Datastore

// Host/ESX
case vtypes.BaseHostEvent:
e := baseEvent.GetHostEvent()
objName = e.Host.Name
ref = &e.Host.Host

// Resource Pool
case vtypes.BaseResourcePoolEvent:
e := baseEvent.GetResourcePoolEvent()
objName = e.ResourcePool.Name
ref = &e.ResourcePool.ResourcePool

// VM
case vtypes.BaseVmEvent:
e := baseEvent.GetVmEvent()
objName = e.Vm.Name
ref = &e.Vm.Vm
}

return ref
return objName, ref
}

// convertToTopic converts an event type to an OpenFaaS subscriber topic, e.g. "VmPoweredOnEvent" to "vm.powered.on"
Expand Down
59 changes: 34 additions & 25 deletions pkg/events/events_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package events

import "testing"
import vtypes "github.com/vmware/govmomi/vim25/types"
import (
"reflect"
"testing"

vtypes "github.com/vmware/govmomi/vim25/types"
)

var (
vmEvent = &vtypes.VmEvent{
Event: vtypes.Event{
Vm: &vtypes.VmEventArgument{
EntityEventArgument: vtypes.EntityEventArgument{
Name: "Windows10-1234",
},
Vm: vtypes.ManagedObjectReference{
Type: "VirtualMachine",
Value: "vm-1234",
Expand All @@ -17,6 +24,9 @@ var (

resourcePoolEvent = &vtypes.ResourcePoolEvent{
ResourcePool: vtypes.ResourcePoolEventArgument{
EntityEventArgument: vtypes.EntityEventArgument{
Name: "Management-RP-1234",
},
ResourcePool: vtypes.ManagedObjectReference{
Type: "ResourcePool",
Value: "resgroup-1234",
Expand All @@ -29,32 +39,31 @@ var (
}
)

var tests = []struct {
name string
event vtypes.BaseEvent
moref *vtypes.ManagedObjectReference
motype string
movalue string
}{
{"valid VM Event", vmEvent, &vmEvent.Vm.Vm, "VirtualMachine", "vm-1234"},
{"valid ResourcePool Event", resourcePoolEvent, &resourcePoolEvent.ResourcePool.ResourcePool, "ResourcePool", "resgroup-1234"},
// assert that ManagedObjectReference will be nil for events we don't support (yet), so it won't be marshaled in the outbound JSON
{"unsupported Event", unsupportedEvent, nil, "", ""},
}
func TestGetObjectNameAndMoRef(t *testing.T) {

func TestGetMoref(t *testing.T) {
for _, test := range tests {
t.Logf("running test: %q", test.name)
ref := getMoref(test.event)
if ref != test.moref {
t.Errorf("Received incorrect MoRef, got: %v, want: %v", ref, test.moref)
}
var testCases = []struct {
name string
event vtypes.BaseEvent
wantMoref *vtypes.ManagedObjectReference
wantObjName string
}{
{"valid VM Event", vmEvent, &vmEvent.Vm.Vm, "Windows10-1234"},
{"valid ResourcePool Event", resourcePoolEvent, &resourcePoolEvent.ResourcePool.ResourcePool, "Management-RP-1234"},
// assert that ManagedObjectReference and ObjectName will be nil for events we don't support (yet), so it won't be marshaled in the outbound JSON
{"unsupported Event", unsupportedEvent, nil, ""},
}

if ref != nil {
if ref.Value != test.movalue {
t.Errorf("Received incorrect MoRef value, got: %v, want: %v", ref.Value, test.movalue)
}
for _, test := range testCases {
name, ref := getObjectNameAndMoref(test.event)

// test MoRef
if eq := reflect.DeepEqual(test.wantMoref, ref); !eq {
t.Errorf("%s: wanted: %v, got: %v", test.name, test.wantMoref, ref)
}

// test ObjectName
if eq := reflect.DeepEqual(test.wantObjName, name); !eq {
t.Errorf("%s: wanted: %v, got: %v", test.name, test.wantObjName, name)
}
}
}

0 comments on commit 92d133a

Please sign in to comment.