Skip to content

Commit

Permalink
Update event subscription (#241)
Browse files Browse the repository at this point in the history
  • Loading branch information
xflipped authored Mar 18, 2023
1 parent 4f0b2dc commit 4c03e55
Show file tree
Hide file tree
Showing 3 changed files with 441 additions and 188 deletions.
150 changes: 121 additions & 29 deletions redfish/eventdestination.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,20 +272,50 @@ func GetEventDestination(c common.Client, uri string) (*EventDestination, error)

// subscriptionPayload is the payload to create the event subscription
type subscriptionPayload struct {
Destination string `json:"Destination"`
EventTypes []EventType `json:"EventTypes"`
HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"`
Oem interface{} `json:"Oem,omitempty"`
Protocol EventDestinationProtocol `json:"Protocol,omitempty"`
Context string `json:"Context,omitempty"`
Destination string `json:"Destination,omitempty"`
EventTypes []EventType `json:"EventTypes,omitempty"`
RegistryPrefixes []string `json:"RegistryPrefixes,omitempty"`
ResourceTypes []string `json:"ResourceTypes,omitempty"`
DeliveryRetryPolicy DeliveryRetryPolicy `json:"DeliveryRetryPolicy,omitempty"`
HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"`
Oem interface{} `json:"Oem,omitempty"`
Protocol EventDestinationProtocol `json:"Protocol,omitempty"`
Context string `json:"Context,omitempty"`
}

// validateCreateEventDestinationParams will validate
// CreateEventDestination parameters

// Deprecated: (v1.5) EventType-based eventing is DEPRECATED in the Redfish schema
// in favor of using RegistryPrefix and ResourceTypes
func validateCreateEventDestinationParams(
uri string,
destination string,
protocol EventDestinationProtocol,
context string,
eventTypes []EventType,
) error {
// validate event types
if len(eventTypes) == 0 {
return fmt.Errorf("at least one event type for subscription should be defined")
}

for _, et := range eventTypes {
if !et.IsValidEventType() {
return fmt.Errorf("invalid event type")
}
}

return validateCreateEventDestinationMandatoryParams(uri, destination, protocol, context)
}

// validateCreateEventDestinationMandatoryParams will validate
// mandatory parameters for CreateEventDestination HTTP POST request
func validateCreateEventDestinationMandatoryParams(
uri string,
destination string,
protocol EventDestinationProtocol,
context string,
) error {
// validate uri
if strings.TrimSpace(uri) == "" {
Expand All @@ -297,19 +327,23 @@ func validateCreateEventDestinationParams(
return fmt.Errorf("empty destination is not valid")
}

if !strings.HasPrefix(destination, "http") {
u, err := url.ParseRequestURI(destination)
if err != nil {
return err
}

if !strings.HasPrefix(u.Scheme, "http") {
return fmt.Errorf("destination should start with http")
}

// validate event types
if len(eventTypes) == 0 {
return fmt.Errorf("at least one event type for subscription should be defined")
// validate protocol
if strings.TrimSpace(string(protocol)) == "" {
return fmt.Errorf("the required property protocol should be defined")
}

for _, et := range eventTypes {
if !et.IsValidEventType() {
return fmt.Errorf("invalid event type")
}
// validate context
if strings.TrimSpace(context) == "" {
return fmt.Errorf("the required property context should be defined")
}

return nil
Expand All @@ -327,6 +361,9 @@ func validateCreateEventDestinationParams(
// it should contain the vendor specific struct that goes inside the Oem session.
// It returns the new subscription URI if the event subscription is created
// with success or any error encountered.

// Deprecated: (v1.5) EventType-based eventing is DEPRECATED in the Redfish schema
// in favor of using RegistryPrefix and ResourceTypes
func CreateEventDestination(
c common.Client,
uri string,
Expand All @@ -337,25 +374,79 @@ func CreateEventDestination(
context string,
oem interface{},
) (string, error) {
// validate input parameters
err := validateCreateEventDestinationParams(
uri,
destination,
eventTypes,
)
// validate mandatory input parameters
if err := validateCreateEventDestinationParams(uri, destination, protocol, context, eventTypes); err != nil {
return "", err
}

if err != nil {
// create subscription payload
s := &subscriptionPayload{
EventTypes: eventTypes,
}

return sendCreateEventDestinationRequest(c, s, uri, destination, httpHeaders, protocol, context, oem)
}

// For Redfish v1.5+
// CreateEventDestination will create a EventDestination instance.
// URI should contain the address of the collection for Event Subscriptions.
// Destination should contain the URL of the destination for events to be sent.
// RegistryPrefixes is the list of the prefixes for the Message Registries
// that contain the MessageIds that are sent to this event destination.
// If RegistryPrefixes is empty on subscription, the client is subscribing to all Message Registries.
// ResourceTypes is the list of Resource Type values (Schema names) that correspond to the OriginOfCondition,
// the version and full namespace should not be specified.
// If ResourceTypes is empty on subscription, the client is subscribing to receive events regardless of ResourceType.
// HttpHeaders is optional and gives the opportunity to specify any arbitrary
// HTTP headers required for the event POST operation.
// Protocol should be the communication protocol of the event endpoint, usually RedfishEventDestinationProtocol.
// Context is a required client-supplied string that is sent with the event notifications.
// DeliveryRetryPolicy is optional, it should contain the subscription delivery retry policy for events,
// where the subscription type is RedfishEvent.
// Oem is optional and gives the opportunity to specify any OEM specific properties,
// it should contain the vendor specific struct that goes inside the Oem session.
// Returns the new subscription URI if the event subscription is created with success or any error encountered.
func CreateEventDestinationInstance(
c common.Client,
uri string,
destination string,
registryPrefixes []string,
resourceTypes []string,
httpHeaders map[string]string,
protocol EventDestinationProtocol,
context string,
deliveryRetryPolicy DeliveryRetryPolicy,
oem interface{},
) (string, error) {
// validate mandatory input parameters
if err := validateCreateEventDestinationMandatoryParams(uri, destination, protocol, context); err != nil {
return "", err
}

// create subscription payload
s := &subscriptionPayload{
Destination: destination,
EventTypes: eventTypes,
Protocol: protocol,
Context: context,
RegistryPrefixes: registryPrefixes,
ResourceTypes: resourceTypes,
DeliveryRetryPolicy: deliveryRetryPolicy,
}

return sendCreateEventDestinationRequest(c, s, uri, destination, httpHeaders, protocol, context, oem)
}

func sendCreateEventDestinationRequest(
c common.Client,
s *subscriptionPayload,
uri string,
destination string,
httpHeaders map[string]string,
protocol EventDestinationProtocol,
context string,
oem interface{},
) (subscriptionLink string, err error) {
s.Destination = destination
s.Protocol = protocol
s.Context = context

// HTTP headers
if len(httpHeaders) > 0 {
s.HTTPHeaders = httpHeaders
Expand All @@ -368,17 +459,18 @@ func CreateEventDestination(

resp, err := c.Post(uri, s)
if err != nil {
return "", err
return
}
defer resp.Body.Close()

// return subscription link from returned location
subscriptionLink := resp.Header.Get("Location")
if urlParser, err := url.ParseRequestURI(subscriptionLink); err == nil {
subscriptionLink = resp.Header.Get("Location")
urlParser, err := url.ParseRequestURI(subscriptionLink)
if err == nil {
subscriptionLink = urlParser.RequestURI()
}

return subscriptionLink, nil
return subscriptionLink, err
}

// DeleteEventDestination will delete a EventDestination.
Expand Down
54 changes: 52 additions & 2 deletions redfish/eventservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ func (eventservice *EventService) GetEventSubscription(uri string) (*EventDestin
// it should contain the vendor specific struct that goes inside the Oem session.
// It returns the new subscription URI if the event subscription is created
// with success or any error encountered.

// Deprecated: (v1.5) EventType-based eventing is DEPRECATED in the Redfish schema
// in favor of using RegistryPrefix and ResourceTypes
func (eventservice *EventService) CreateEventSubscription(
destination string,
eventTypes []EventType,
Expand All @@ -326,6 +329,53 @@ func (eventservice *EventService) CreateEventSubscription(
)
}

// For Redfish v1.5+
// CreateEventSubscription creates the subscription using the event service.
// Destination should contain the URL of the destination for events to be sent.
// RegistryPrefixes is the list of the prefixes for the Message Registries
// that contain the MessageIds that are sent to this event destination.
// If RegistryPrefixes is empty on subscription, the client is subscribing to all Message Registries.
// ResourceTypes is the list of Resource Type values (Schema names) that correspond to the OriginOfCondition,
// the version and full namespace should not be specified.
// If ResourceTypes is empty on subscription, the client is subscribing to receive events regardless of ResourceType.
// HttpHeaders is optional and gives the opportunity to specify any arbitrary
// HTTP headers required for the event POST operation.
// Protocol should be the communication protocol of the event endpoint, usually RedfishEventDestinationProtocol.
// Context is a required client-supplied string that is sent with the event notifications.
// DeliveryRetryPolicy is optional, it should contain the subscription delivery retry policy for events,
// where the subscription type is RedfishEvent.
// Oem is optional and gives the opportunity to specify any OEM specific properties,
// it should contain the vendor specific struct that goes inside the Oem session.
// It returns the new subscription URI if the event subscription is created
// with success or any error encountered.
func (eventservice *EventService) CreateEventSubscriptionInstance(
destination string,
registryPrefixes []string,
resourceTypes []string,
httpHeaders map[string]string,
protocol EventDestinationProtocol,
context string,
deliveryRetryPolicy DeliveryRetryPolicy,
oem interface{},
) (string, error) {
if strings.TrimSpace(eventservice.Subscriptions) == "" {
return "", fmt.Errorf("empty subscription link in the event service")
}

return CreateEventDestinationInstance(
eventservice.Client,
eventservice.Subscriptions,
destination,
registryPrefixes,
resourceTypes,
httpHeaders,
protocol,
context,
deliveryRetryPolicy,
oem,
)
}

// DeleteEventSubscription deletes a specific subscription using the event service.
func (eventservice *EventService) DeleteEventSubscription(uri string) error {
return DeleteEventDestination(eventservice.Client, uri)
Expand All @@ -339,8 +389,8 @@ func (eventservice *EventService) SubmitTestEvent(message string) error {
EventGroupID string `json:"EventGroupId"`
EventID string `json:"EventId"`
EventTimestamp string
EventType string
Message string
EventType string `json:"EventType,omitempty"`
Message string `json:"Message,omitempty"`
MessageArgs []string
MessageID string `json:"MessageId"`
OriginOfCondition string
Expand Down
Loading

0 comments on commit 4c03e55

Please sign in to comment.