Skip to content

Commit

Permalink
Update Hw event structures with Redfish schema (#30)
Browse files Browse the repository at this point in the history
* Update Hw event structures with Redfish schema

Signed-off-by: Jack Ding <[email protected]>

* addressing review comments

Signed-off-by: Jack Ding <[email protected]>

* remove 'omitempty' for required json fields

Signed-off-by: Jack Ding <[email protected]>
  • Loading branch information
jzding authored Jul 23, 2021
1 parent 4072da5 commit a808941
Show file tree
Hide file tree
Showing 17 changed files with 602 additions and 410 deletions.
13 changes: 6 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ go 1.15

require (
github.com/Azure/go-amqp v0.12.7
github.com/cloudevents/sdk-go/protocol/amqp/v2 v2.3.1-0.20210302080936-5c462007a5d5
github.com/cloudevents/sdk-go/v2 v2.3.1-0.20210302080936-5c462007a5d5
github.com/google/go-cmp v0.5.5
github.com/google/uuid v1.1.2
github.com/json-iterator/go v1.1.10
github.com/prometheus/client_golang v1.10.0
github.com/cloudevents/sdk-go/protocol/amqp/v2 v2.4.1
github.com/cloudevents/sdk-go/v2 v2.4.1
github.com/google/go-cmp v0.5.6
github.com/google/uuid v1.3.0
github.com/json-iterator/go v1.1.11
github.com/prometheus/client_golang v1.11.0
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
339 changes: 19 additions & 320 deletions go.sum

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/channel/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ type DataChan struct {
Data *cloudevents.Event
Status Status
//Type defines type of data (Notification,Metric,Status)
Type Type
Type Type
// OnReceiveFn to do on OnReceive
OnReceiveFn func(e cloudevents.Event)
// OnReceiveOverrideFn Optional for event, but override for status pings.This is an override function on receiving msg by amqp listener,
// if not set then the data is sent to out channel and processed by side car default method
OnReceiveOverrideFn func(e cloudevents.Event,dataChan *DataChan) error
OnReceiveOverrideFn func(e cloudevents.Event, dataChan *DataChan) error
// ProcessEventFn Optional, this allows to customize message handler thar was received at the out channel
ProcessEventFn func(e interface{}) error
}
5 changes: 2 additions & 3 deletions pkg/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,12 @@ type Event struct {
DataContentType *string `json:"dataContentType" example:"application/json"`
// Time - A Timestamp when the event happened.
// +required
Time *types.Timestamp `json:"time,omitempty" example:"2021-02-05T17:31:00Z"`
Time *types.Timestamp `json:"time" example:"2021-02-05T17:31:00Z"`
// DataSchema - A link to the schema that the `Data` attribute adheres to.
// +optional
DataSchema *types.URI `json:"dataSchema,omitempty"`

Data *Data `json:"data,omitempty" `
// +required
Data *Data `json:"data" `
}

// String returns a pretty-printed representation of the Event.
Expand Down
3 changes: 1 addition & 2 deletions pkg/event/event_ce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package event_test

import (
"encoding/json"

ce "github.com/cloudevents/sdk-go/v2"
"github.com/google/uuid"
cneevent "github.com/redhat-cne/sdk-go/pkg/event"
Expand Down Expand Up @@ -102,7 +103,6 @@ func TestEvent_NewCloudEvent(t *testing.T) {
log.Printf("cloud events %s\n", string(gotBytes))
if tc.wantErr != nil {
require.Error(t, err, *tc.wantErr)
return
}
assertCEJsonEquals(t, tc.want, gotBytes)
})
Expand Down Expand Up @@ -144,7 +144,6 @@ func TestEvent_GetCloudNativeEvents(t *testing.T) {
gotBytes, err := json.Marshal(event)
if tc.wantErr != nil {
require.Error(t, err, *tc.wantErr)
return
}
assertCNEJsonEquals(t, tc.want, gotBytes)

Expand Down
17 changes: 7 additions & 10 deletions pkg/hwevent/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,25 @@ type Event struct {
DataContentType *string `json:"dataContentType" example:"application/json"`
// Time - A Timestamp when the event happened.
// +required
Time *types.Timestamp `json:"time,omitempty" example:"2021-02-05T17:31:00Z"`
Time *types.Timestamp `json:"time" example:"2021-02-05T17:31:00Z"`
// DataSchema - A link to the schema that the `Data` attribute adheres to.
// +optional
DataSchema *types.URI `json:"dataSchema,omitempty"`

Data *Data `json:"data,omitempty" `
// +required
Data *Data `json:"data" `
}

// String returns a pretty-printed representation of the Event.
func (e Event) String() string {
b := strings.Builder{}
b.WriteString(" id: " + e.ID + "\n")
b.WriteString(" type: " + e.Type + "\n")
b.WriteString("id: " + e.ID + "\n")
b.WriteString("type: " + e.Type + "\n")
if e.Time != nil {
b.WriteString(" time: " + e.Time.String() + "\n")
b.WriteString("time: " + e.Time.String() + "\n")
}

b.WriteString(" data: \n")
b.WriteString(" version: " + e.Data.Version + "\n")
b.WriteString(" values: \n")
b.WriteString(" data: " + string(e.Data.Data) + "\n")
b.WriteString("data:")
b.WriteString(e.Data.String())

return b.String()
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/hwevent/event_ce.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (e *Event) GetCloudNativeEvents(ce *cloudevent.Event) (err error) {
}
data := Data{}
if err = json.Unmarshal(ce.Data(), &data); err != nil {
return
return err
}
e.SetDataContentType(ApplicationJSON)
e.SetTime(ce.Time())
Expand Down
31 changes: 23 additions & 8 deletions pkg/hwevent/event_ce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

ce "github.com/cloudevents/sdk-go/v2"
"github.com/google/uuid"
hwevent "github.com/redhat-cne/sdk-go/pkg/hwevent"
"github.com/redhat-cne/sdk-go/pkg/hwevent"
cnepubsub "github.com/redhat-cne/sdk-go/pkg/pubsub"
"github.com/redhat-cne/sdk-go/pkg/types"
hweventv1 "github.com/redhat-cne/sdk-go/v1/hwevent"
Expand All @@ -36,15 +36,33 @@ var (
id = uuid.New().String()
data hwevent.Data
pubsub cnepubsub.PubSub
)

const RedfishEvent = `{"@odata.context":"/redfish/v1/$metadata#Event.Event","@odata.type":"#Event.v1_0_0.Event","Events":[{"EventId":"TestEventId","EventTimestamp":"2019-07-29T15:13:49Z","EventType":"Alert","Message":"Test Event","MessageArgs":["NoAMS","Busy","Cached"],"MessageId":"iLOEvents.2.1.ServerPoweredOff","OriginOfCondition":"/redfish/v1/Systems/1/","Severity":"OK"}],"Name":"Events"}`
EVENT_RECORD_TMP0100 = hwevent.EventRecord{
Context: "any string is valid",
EventID: "2162",
EventTimestamp: "2021-07-13T15:07:59+0300",
EventType: "Alert",
MemberID: "615703",
Message: "The system board Inlet temperature is less than the lower warning threshold.",
MessageArgs: []string{"Inlet"},
MessageID: "TMP0100",
Severity: "Warning",
}

REDFISH_EVENT_TMP0100 = hwevent.RedfishEvent{
OdataContext: "/redfish/v1/$metadata#Event.Event",
OdataType: "#Event.v1_3_0.Event",
Context: "any string is valid",
Events: []hwevent.EventRecord{EVENT_RECORD_TMP0100},
ID: "5e004f5a-e3d1-11eb-ae9c-3448edf18a38",
Name: "Event Array",
}
)

func setup() {
data = hwevent.Data{}
data.SetData([]byte(RedfishEvent)) //nolint:errcheck
data.SetData(&REDFISH_EVENT_TMP0100) //nolint:errcheck
pubsub.SetID(id)

}

func TestEvent_NewCloudEvent(t *testing.T) {
Expand Down Expand Up @@ -88,7 +106,6 @@ func TestEvent_NewCloudEvent(t *testing.T) {
log.Printf("cloud events %s\n", string(gotBytes))
if tc.wantErr != nil {
require.Error(t, err, *tc.wantErr)
return
}
assertCEJsonEquals(t, tc.want, gotBytes)
})
Expand Down Expand Up @@ -130,10 +147,8 @@ func TestEvent_GetCloudNativeEvents(t *testing.T) {
gotBytes, err := json.Marshal(event)
if tc.wantErr != nil {
require.Error(t, err, *tc.wantErr)
return
}
assertCNEJsonEquals(t, tc.want, gotBytes)

})
}
}
Expand Down
189 changes: 185 additions & 4 deletions pkg/hwevent/event_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,198 @@ package hwevent

import (
"fmt"
"strconv"
"strings"
)

// The structs defined here are based on Redfish Schema Bundle 2019.2.

// EventRecord is defined in Redfish Event_v1_4_1_EventRecord
// https://redfish.dmtf.org/schemas/v1/Event.v1_4_1.json
// Additional information returned from Message Registry is added
// from https://redfish.dmtf.org/schemas/v1/Message.v1_0_8.json
// Required fields: EventType, MessageId, MemberId
type EventRecord struct {
// The Actions property shall contain the available actions
// for this resource.
// +optional
Actions []byte `json:"Actions,omitempty"`
// *deprecated* This property has been Deprecated in favor of Context
// found at the root level of the object.
// +optional
Context string `json:"Context,omitempty"`
// This value is the identifier used to correlate events that
// came from the same cause.
// +optional
EventGroupID int `json:"EventGroupId,omitempty"`
// The value of this property shall indicate a unique identifier
// for the event, the format of which is implementation dependent.
// +optional
EventID string `json:"EventId,omitempty"`
// This is time the event occurred.
// +optional
EventTimestamp string `json:"EventTimestamp,omitempty"`
// *deprecated* This property has been deprecated. Starting Redfish
// Spec 1.6 (Event 1.3), subscriptions are based on RegistryId and ResourceType
// and not EventType.
// This indicates the type of event sent, according to the definitions
// in the EventService.
// +required
EventType string `json:"EventType"`
// This is the identifier for the member within the collection.
// +required
MemberID string `json:"MemberId"`
// This property shall contain an optional human readable
// message.
// +optional
Message string `json:"Message,omitempty"`
// This array of message arguments are substituted for the arguments
// in the message when looked up in the message registry.
// +optional
MessageArgs []string `json:"MessageArgs,omitempty"`
// This property shall be a key into message registry as
// described in the Redfish specification.
// +required
MessageID string `json:"MessageId"`
// This is the manufacturer/provider specific extension
// +optional
Oem []byte `json:"Oem,omitempty"`
// This indicates the resource that originated the condition that
// caused the event to be generated.
// +optional
OriginOfCondition string `json:"OriginOfCondition,omitempty"`
// This is the severity of the event.
// +optional
Severity string `json:"Severity,omitempty"`
// The following fields are defined in schema Message.v1_0_8
// These are additional information returned from Message Registry.
// Used to provide suggestions on how to resolve the situation that caused the error.
// +optional
Resolution string `json:"Resolution"`
}

// String returns a pretty-printed representation of the EventRecord.
func (e EventRecord) String() string {
b := strings.Builder{}
b.WriteString("\n")
if e.Actions != nil {
b.WriteString(" Actions: " + string(e.Actions) + "\n")
}
if e.Context != "" {
b.WriteString(" Context: " + e.Context + "\n")
}
// EventGroupId shows 0 by default
b.WriteString(" EventGroupId: " + strconv.Itoa(e.EventGroupID) + "\n")
if e.EventID != "" {
b.WriteString(" EventId: " + e.EventID + "\n")
}
if e.EventTimestamp != "" {
b.WriteString(" EventTimestamp: " + e.EventTimestamp + "\n")
}
b.WriteString(" EventType: " + e.EventType + "\n")
b.WriteString(" MemberId: " + e.MemberID + "\n")
if e.Message != "" {
b.WriteString(" Message: " + e.Message + "\n")
}
if e.MessageArgs != nil {
b.WriteString(" MessageArgs: ")
for _, arg := range e.MessageArgs {
b.WriteString(arg + ", ")
}
b.WriteString("\n")
}
b.WriteString(" MessageId: " + e.MessageID + "\n")
if e.Oem != nil {
b.WriteString(" Oem: " + string(e.Oem) + "\n")
}
if e.OriginOfCondition != "" {
b.WriteString(" OriginOfCondition: " + e.OriginOfCondition + "\n")
}
if e.Severity != "" {
b.WriteString(" Severity: " + e.Severity + "\n")
}
if e.Resolution != "" {
b.WriteString(" Resolution: " + e.Resolution + "\n")
}
return b.String()
}

// RedfishEvent is defined in Redfish schema Event.v1_4_1.json
// https://redfish.dmtf.org/schemas/v1/Event.v1_4_1.json
// The Event schema describes the JSON payload received by an Event Destination,
// which has subscribed to event notification, when events occur. This Resource
// contains data about events, including descriptions, severity, and a MessageId
// link to a Message Registry that can be accessed for further information.
//
// Required fields: @odata.type, Events, Id, Name
type RedfishEvent struct {
// +optional
OdataContext string `json:"@odata.context,omitempty"`
// +required
OdataType string `json:"@odata.type"`
// The available actions for this resource.
// +optional
Actions []byte `json:"Actions,omitempty"`
// A context can be supplied at subscription time. This property
// is the context value supplied by the subscriber.
// +optional
Context string `json:"Context,omitempty"`
// +optional
Description string `json:"Description,omitempty"`
// +required
Events []EventRecord `json:"Events"`
// +required
ID string `json:"Id"`
// +required
Name string `json:"Name"`
// This is the manufacturer/provider specific extension
// +optional
Oem []byte `json:"Oem,omitempty"`
}

// String returns a pretty-printed representation of the RedfishEvent.
func (e RedfishEvent) String() string {
b := strings.Builder{}
if e.OdataContext != "" {
b.WriteString("\n @odata.context: " + e.OdataContext + "\n")
}
b.WriteString(" @odata.type: " + e.OdataType + "\n")
if e.Actions != nil {
b.WriteString(" Actions: " + string(e.Actions) + "\n")
}
if e.Context != "" {
b.WriteString(" Context: " + e.Context + "\n")
}
b.WriteString(" Id: " + e.ID + "\n")
b.WriteString(" Name: " + e.Name + "\n")
if e.Oem != nil {
b.WriteString(" Oem: " + string(e.Oem) + "\n")
}
for i, e := range e.Events {
b.WriteString(" Events[" + strconv.Itoa(i) + "]:")
b.WriteString(e.String())
}
return b.String()
}

// Data ... cloud native events data
// Data Json payload is as follows,
//{
// "version": "v1.0",
// "version": "v1.4.1",
//
//}
type Data struct {
Version string `json:"version" example:"v1"`
Data []byte `json:"data"`
Version string `json:"version" example:"v1"`
Data *RedfishEvent `json:"data"`
}

// String returns a pretty-printed representation of the Data.
func (d Data) String() string {
b := strings.Builder{}
b.WriteString("\n version: " + d.Version + "\n")
b.WriteString(" data:")
b.WriteString(d.Data.String())
return b.String()
}

// SetVersion ...
Expand All @@ -45,6 +226,6 @@ func (d *Data) GetVersion() string {
}

// SetData ...
func (d *Data) SetData(b []byte) {
func (d *Data) SetData(b *RedfishEvent) {
d.Data = b
}
Loading

0 comments on commit a808941

Please sign in to comment.