From: Anssi Mannila Date: Thu, 16 Sep 2021 11:48:04 +0000 (+0300) Subject: Subscription REST interface update X-Git-Tag: v0.8.5^0 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=41e3b5845256a1ef3ae70fac702ee545ce5c2905;p=ric-plt%2Fxapp-frame.git Subscription REST interface update Added: - E2 interface subscription retry and timeout directives - Reject cause - Descriptive error inforamtion - Source of error information - Interface where timeout happened Change-Id: Ie08f53135858137729a90995027a42bc82b08528 Signed-off-by: Anssi Mannila --- diff --git a/api/xapp_rest_api.yaml b/api/xapp_rest_api.yaml index 2890b90..8f08dd9 100644 --- a/api/xapp_rest_api.yaml +++ b/api/xapp_rest_api.yaml @@ -1,7 +1,7 @@ swagger: '2.0' info: description: This is the initial REST API for RIC subscription - version: 0.0.2 + version: 0.0.3 title: RIC subscription license: name: Apache 2.0 @@ -243,6 +243,25 @@ definitions: type: integer minimum: 0 maximum: 4095 + E2SubscriptionDirectives: + type: object + properties: + E2TimeoutTimerValue: + description: How long time response is waited from E2 node + type: integer + default: 2 + minimum: 1 + maximum: 10 + E2RetryCount: + description: How many times E2 subscription request is retried + type: integer + default: 2 + minimum: 0 + maximum: 10 + RMRRoutingNeeded: + description: Subscription needs RMR route from E2Term to xApp + type: boolean + default: True SubscriptionDetails: $ref: '#/definitions/SubscriptionDetailsList' SubscriptionResponse: @@ -263,6 +282,8 @@ definitions: - XappEventInstanceId - E2EventInstanceId - ErrorCause + - ErrorSource + - TimeoutType properties: XappEventInstanceId: type: integer @@ -272,9 +293,32 @@ definitions: type: integer minimum: 0 maximum: 65535 + RejectCause: + description: Reason for REST subscription rejection. + type: string + default: None + enum: + - None + - REST-subscription-ongoing # xApp should retry after delay + - REST-subscription-delete-ongoing # xApp should retry after delay + - Invalid-REST-request-message + - REST-subscription-with-given-id-does-not-exist + - E2-interface-down + - Other ErrorCause: - description: Empty string when no error. + description: Descriptive error cause. Empty string when no error. + type: string + default: '' + ErrorSource: + description: Source of error cause. + type: string + default: None + enum: [None, SUBMGR, RTMGR, DBAAS, ASN1, E2Node] + TimeoutType: + description: Type timeout. xApp should retry if timeout occours. type: string + default: None + enum: [None, E2-Timeout, RTMGR-Timeout, DBAAS-Timeout] SubscriptionData: type: object properties: diff --git a/pkg/clientmodel/subscription_details.go b/pkg/clientmodel/subscription_details.go deleted file mode 100644 index 05677cd..0000000 --- a/pkg/clientmodel/subscription_details.go +++ /dev/null @@ -1,97 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package clientmodel - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - strfmt "github.com/go-openapi/strfmt" - - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// SubscriptionDetails subscription details -// swagger:model SubscriptionDetails -type SubscriptionDetails struct { - - // action to be setup list - // Required: true - ActionToBeSetupList ActionsToBeSetup `json:"ActionToBeSetupList"` - - // event trigger list - // Required: true - EventTriggerList *EventTriggerDefinition `json:"EventTriggerList"` -} - -// Validate validates this subscription details -func (m *SubscriptionDetails) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateActionToBeSetupList(formats); err != nil { - res = append(res, err) - } - - if err := m.validateEventTriggerList(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *SubscriptionDetails) validateActionToBeSetupList(formats strfmt.Registry) error { - - if err := validate.Required("ActionToBeSetupList", "body", m.ActionToBeSetupList); err != nil { - return err - } - - if err := m.ActionToBeSetupList.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("ActionToBeSetupList") - } - return err - } - - return nil -} - -func (m *SubscriptionDetails) validateEventTriggerList(formats strfmt.Registry) error { - - if err := validate.Required("EventTriggerList", "body", m.EventTriggerList); err != nil { - return err - } - - if m.EventTriggerList != nil { - if err := m.EventTriggerList.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("EventTriggerList") - } - return err - } - } - - return nil -} - -// MarshalBinary interface implementation -func (m *SubscriptionDetails) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *SubscriptionDetails) UnmarshalBinary(b []byte) error { - var res SubscriptionDetails - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/pkg/clientmodel/subscription_instance.go b/pkg/clientmodel/subscription_instance.go index 4f099a6..8c6ae48 100644 --- a/pkg/clientmodel/subscription_instance.go +++ b/pkg/clientmodel/subscription_instance.go @@ -6,6 +6,8 @@ package clientmodel // Editing this file might prove futile when you re-run the swagger generate command import ( + "encoding/json" + "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" @@ -23,10 +25,24 @@ type SubscriptionInstance struct { // Minimum: 0 E2EventInstanceID *int64 `json:"E2EventInstanceId"` - // Empty string when no error. + // Descriptive error cause. Empty string when no error. // Required: true ErrorCause *string `json:"ErrorCause"` + // Source of error cause. + // Required: true + // Enum: [None SUBMGR RTMGR DBAAS ASN1 E2Node] + ErrorSource *string `json:"ErrorSource"` + + // Reason for REST subscription rejection. + // Enum: [None REST-subscription-ongoing REST-subscription-delete-ongoing Invalid-REST-request-message REST-subscription-with-given-id-does-not-exist E2-interface-down Other] + RejectCause *string `json:"RejectCause,omitempty"` + + // Type timeout. xApp should retry if timeout occours. + // Required: true + // Enum: [None E2-Timeout RTMGR-Timeout DBAAS-Timeout] + TimeoutType *string `json:"TimeoutType"` + // xapp event instance Id // Required: true // Maximum: 65535 @@ -46,6 +62,18 @@ func (m *SubscriptionInstance) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateErrorSource(formats); err != nil { + res = append(res, err) + } + + if err := m.validateRejectCause(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTimeoutType(formats); err != nil { + res = append(res, err) + } + if err := m.validateXappEventInstanceID(formats); err != nil { res = append(res, err) } @@ -82,6 +110,168 @@ func (m *SubscriptionInstance) validateErrorCause(formats strfmt.Registry) error return nil } +var subscriptionInstanceTypeErrorSourcePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["None","SUBMGR","RTMGR","DBAAS","ASN1","E2Node"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + subscriptionInstanceTypeErrorSourcePropEnum = append(subscriptionInstanceTypeErrorSourcePropEnum, v) + } +} + +const ( + + // SubscriptionInstanceErrorSourceNone captures enum value "None" + SubscriptionInstanceErrorSourceNone string = "None" + + // SubscriptionInstanceErrorSourceSUBMGR captures enum value "SUBMGR" + SubscriptionInstanceErrorSourceSUBMGR string = "SUBMGR" + + // SubscriptionInstanceErrorSourceRTMGR captures enum value "RTMGR" + SubscriptionInstanceErrorSourceRTMGR string = "RTMGR" + + // SubscriptionInstanceErrorSourceDBAAS captures enum value "DBAAS" + SubscriptionInstanceErrorSourceDBAAS string = "DBAAS" + + // SubscriptionInstanceErrorSourceASN1 captures enum value "ASN1" + SubscriptionInstanceErrorSourceASN1 string = "ASN1" + + // SubscriptionInstanceErrorSourceE2Node captures enum value "E2Node" + SubscriptionInstanceErrorSourceE2Node string = "E2Node" +) + +// prop value enum +func (m *SubscriptionInstance) validateErrorSourceEnum(path, location string, value string) error { + if err := validate.Enum(path, location, value, subscriptionInstanceTypeErrorSourcePropEnum); err != nil { + return err + } + return nil +} + +func (m *SubscriptionInstance) validateErrorSource(formats strfmt.Registry) error { + + if err := validate.Required("ErrorSource", "body", m.ErrorSource); err != nil { + return err + } + + // value enum + if err := m.validateErrorSourceEnum("ErrorSource", "body", *m.ErrorSource); err != nil { + return err + } + + return nil +} + +var subscriptionInstanceTypeRejectCausePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["None","REST-subscription-ongoing","REST-subscription-delete-ongoing","Invalid-REST-request-message","REST-subscription-with-given-id-does-not-exist","E2-interface-down","Other"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + subscriptionInstanceTypeRejectCausePropEnum = append(subscriptionInstanceTypeRejectCausePropEnum, v) + } +} + +const ( + + // SubscriptionInstanceRejectCauseNone captures enum value "None" + SubscriptionInstanceRejectCauseNone string = "None" + + // SubscriptionInstanceRejectCauseRESTSubscriptionOngoing captures enum value "REST-subscription-ongoing" + SubscriptionInstanceRejectCauseRESTSubscriptionOngoing string = "REST-subscription-ongoing" + + // SubscriptionInstanceRejectCauseRESTSubscriptionDeleteOngoing captures enum value "REST-subscription-delete-ongoing" + SubscriptionInstanceRejectCauseRESTSubscriptionDeleteOngoing string = "REST-subscription-delete-ongoing" + + // SubscriptionInstanceRejectCauseInvalidRESTRequestMessage captures enum value "Invalid-REST-request-message" + SubscriptionInstanceRejectCauseInvalidRESTRequestMessage string = "Invalid-REST-request-message" + + // SubscriptionInstanceRejectCauseRESTSubscriptionWithGivenIDDoesNotExist captures enum value "REST-subscription-with-given-id-does-not-exist" + SubscriptionInstanceRejectCauseRESTSubscriptionWithGivenIDDoesNotExist string = "REST-subscription-with-given-id-does-not-exist" + + // SubscriptionInstanceRejectCauseE2InterfaceDown captures enum value "E2-interface-down" + SubscriptionInstanceRejectCauseE2InterfaceDown string = "E2-interface-down" + + // SubscriptionInstanceRejectCauseOther captures enum value "Other" + SubscriptionInstanceRejectCauseOther string = "Other" +) + +// prop value enum +func (m *SubscriptionInstance) validateRejectCauseEnum(path, location string, value string) error { + if err := validate.Enum(path, location, value, subscriptionInstanceTypeRejectCausePropEnum); err != nil { + return err + } + return nil +} + +func (m *SubscriptionInstance) validateRejectCause(formats strfmt.Registry) error { + + if swag.IsZero(m.RejectCause) { // not required + return nil + } + + // value enum + if err := m.validateRejectCauseEnum("RejectCause", "body", *m.RejectCause); err != nil { + return err + } + + return nil +} + +var subscriptionInstanceTypeTimeoutTypePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["None","E2-Timeout","RTMGR-Timeout","DBAAS-Timeout"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + subscriptionInstanceTypeTimeoutTypePropEnum = append(subscriptionInstanceTypeTimeoutTypePropEnum, v) + } +} + +const ( + + // SubscriptionInstanceTimeoutTypeNone captures enum value "None" + SubscriptionInstanceTimeoutTypeNone string = "None" + + // SubscriptionInstanceTimeoutTypeE2Timeout captures enum value "E2-Timeout" + SubscriptionInstanceTimeoutTypeE2Timeout string = "E2-Timeout" + + // SubscriptionInstanceTimeoutTypeRTMGRTimeout captures enum value "RTMGR-Timeout" + SubscriptionInstanceTimeoutTypeRTMGRTimeout string = "RTMGR-Timeout" + + // SubscriptionInstanceTimeoutTypeDBAASTimeout captures enum value "DBAAS-Timeout" + SubscriptionInstanceTimeoutTypeDBAASTimeout string = "DBAAS-Timeout" +) + +// prop value enum +func (m *SubscriptionInstance) validateTimeoutTypeEnum(path, location string, value string) error { + if err := validate.Enum(path, location, value, subscriptionInstanceTypeTimeoutTypePropEnum); err != nil { + return err + } + return nil +} + +func (m *SubscriptionInstance) validateTimeoutType(formats strfmt.Registry) error { + + if err := validate.Required("TimeoutType", "body", m.TimeoutType); err != nil { + return err + } + + // value enum + if err := m.validateTimeoutTypeEnum("TimeoutType", "body", *m.TimeoutType); err != nil { + return err + } + + return nil +} + func (m *SubscriptionInstance) validateXappEventInstanceID(formats strfmt.Registry) error { if err := validate.Required("XappEventInstanceId", "body", m.XappEventInstanceID); err != nil { diff --git a/pkg/clientmodel/subscription_params.go b/pkg/clientmodel/subscription_params.go index fdd41ca..b116e50 100644 --- a/pkg/clientmodel/subscription_params.go +++ b/pkg/clientmodel/subscription_params.go @@ -21,6 +21,9 @@ type SubscriptionParams struct { // Required: true ClientEndpoint *SubscriptionParamsClientEndpoint `json:"ClientEndpoint"` + // e2 subscription directives + E2SubscriptionDirectives *SubscriptionParamsE2SubscriptionDirectives `json:"E2SubscriptionDirectives,omitempty"` + // meid // Required: true Meid *string `json:"Meid"` @@ -47,6 +50,10 @@ func (m *SubscriptionParams) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateE2SubscriptionDirectives(formats); err != nil { + res = append(res, err) + } + if err := m.validateMeid(formats); err != nil { res = append(res, err) } @@ -83,6 +90,24 @@ func (m *SubscriptionParams) validateClientEndpoint(formats strfmt.Registry) err return nil } +func (m *SubscriptionParams) validateE2SubscriptionDirectives(formats strfmt.Registry) error { + + if swag.IsZero(m.E2SubscriptionDirectives) { // not required + return nil + } + + if m.E2SubscriptionDirectives != nil { + if err := m.E2SubscriptionDirectives.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("E2SubscriptionDirectives") + } + return err + } + } + + return nil +} + func (m *SubscriptionParams) validateMeid(formats strfmt.Registry) error { if err := validate.Required("Meid", "body", m.Meid); err != nil { @@ -231,3 +256,92 @@ func (m *SubscriptionParamsClientEndpoint) UnmarshalBinary(b []byte) error { *m = res return nil } + +// SubscriptionParamsE2SubscriptionDirectives subscription params e2 subscription directives +// +// swagger:model SubscriptionParamsE2SubscriptionDirectives +type SubscriptionParamsE2SubscriptionDirectives struct { + + // How many times E2 subscription request is retried + // Maximum: 10 + // Minimum: 0 + E2RetryCount *int64 `json:"E2RetryCount,omitempty"` + + // How long time response is waited from E2 node + // Maximum: 10 + // Minimum: 1 + E2TimeoutTimerValue int64 `json:"E2TimeoutTimerValue,omitempty"` + + // Subscription needs RMR route from E2Term to xApp + RMRRoutingNeeded *bool `json:"RMRRoutingNeeded,omitempty"` +} + +// Validate validates this subscription params e2 subscription directives +func (m *SubscriptionParamsE2SubscriptionDirectives) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateE2RetryCount(formats); err != nil { + res = append(res, err) + } + + if err := m.validateE2TimeoutTimerValue(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *SubscriptionParamsE2SubscriptionDirectives) validateE2RetryCount(formats strfmt.Registry) error { + + if swag.IsZero(m.E2RetryCount) { // not required + return nil + } + + if err := validate.MinimumInt("E2SubscriptionDirectives"+"."+"E2RetryCount", "body", int64(*m.E2RetryCount), 0, false); err != nil { + return err + } + + if err := validate.MaximumInt("E2SubscriptionDirectives"+"."+"E2RetryCount", "body", int64(*m.E2RetryCount), 10, false); err != nil { + return err + } + + return nil +} + +func (m *SubscriptionParamsE2SubscriptionDirectives) validateE2TimeoutTimerValue(formats strfmt.Registry) error { + + if swag.IsZero(m.E2TimeoutTimerValue) { // not required + return nil + } + + if err := validate.MinimumInt("E2SubscriptionDirectives"+"."+"E2TimeoutTimerValue", "body", int64(m.E2TimeoutTimerValue), 1, false); err != nil { + return err + } + + if err := validate.MaximumInt("E2SubscriptionDirectives"+"."+"E2TimeoutTimerValue", "body", int64(m.E2TimeoutTimerValue), 10, false); err != nil { + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *SubscriptionParamsE2SubscriptionDirectives) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *SubscriptionParamsE2SubscriptionDirectives) UnmarshalBinary(b []byte) error { + var res SubscriptionParamsE2SubscriptionDirectives + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/pkg/models/subscription_details.go b/pkg/models/subscription_details.go deleted file mode 100644 index 69f6121..0000000 --- a/pkg/models/subscription_details.go +++ /dev/null @@ -1,97 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - strfmt "github.com/go-openapi/strfmt" - - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// SubscriptionDetails subscription details -// swagger:model SubscriptionDetails -type SubscriptionDetails struct { - - // action to be setup list - // Required: true - ActionToBeSetupList ActionsToBeSetup `json:"ActionToBeSetupList"` - - // event trigger list - // Required: true - EventTriggerList *EventTriggerDefinition `json:"EventTriggerList"` -} - -// Validate validates this subscription details -func (m *SubscriptionDetails) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateActionToBeSetupList(formats); err != nil { - res = append(res, err) - } - - if err := m.validateEventTriggerList(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *SubscriptionDetails) validateActionToBeSetupList(formats strfmt.Registry) error { - - if err := validate.Required("ActionToBeSetupList", "body", m.ActionToBeSetupList); err != nil { - return err - } - - if err := m.ActionToBeSetupList.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("ActionToBeSetupList") - } - return err - } - - return nil -} - -func (m *SubscriptionDetails) validateEventTriggerList(formats strfmt.Registry) error { - - if err := validate.Required("EventTriggerList", "body", m.EventTriggerList); err != nil { - return err - } - - if m.EventTriggerList != nil { - if err := m.EventTriggerList.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("EventTriggerList") - } - return err - } - } - - return nil -} - -// MarshalBinary interface implementation -func (m *SubscriptionDetails) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *SubscriptionDetails) UnmarshalBinary(b []byte) error { - var res SubscriptionDetails - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/pkg/models/subscription_instance.go b/pkg/models/subscription_instance.go index fa3c3a7..e028de9 100644 --- a/pkg/models/subscription_instance.go +++ b/pkg/models/subscription_instance.go @@ -6,6 +6,8 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( + "encoding/json" + "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" @@ -23,10 +25,24 @@ type SubscriptionInstance struct { // Minimum: 0 E2EventInstanceID *int64 `json:"E2EventInstanceId"` - // Empty string when no error. + // Descriptive error cause. Empty string when no error. // Required: true ErrorCause *string `json:"ErrorCause"` + // Source of error cause. + // Required: true + // Enum: [None SUBMGR RTMGR DBAAS ASN1 E2Node] + ErrorSource *string `json:"ErrorSource"` + + // Reason for REST subscription rejection. + // Enum: [None REST-subscription-ongoing REST-subscription-delete-ongoing Invalid-REST-request-message REST-subscription-with-given-id-does-not-exist E2-interface-down Other] + RejectCause *string `json:"RejectCause,omitempty"` + + // Type timeout. xApp should retry if timeout occours. + // Required: true + // Enum: [None E2-Timeout RTMGR-Timeout DBAAS-Timeout] + TimeoutType *string `json:"TimeoutType"` + // xapp event instance Id // Required: true // Maximum: 65535 @@ -46,6 +62,18 @@ func (m *SubscriptionInstance) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateErrorSource(formats); err != nil { + res = append(res, err) + } + + if err := m.validateRejectCause(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTimeoutType(formats); err != nil { + res = append(res, err) + } + if err := m.validateXappEventInstanceID(formats); err != nil { res = append(res, err) } @@ -82,6 +110,168 @@ func (m *SubscriptionInstance) validateErrorCause(formats strfmt.Registry) error return nil } +var subscriptionInstanceTypeErrorSourcePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["None","SUBMGR","RTMGR","DBAAS","ASN1","E2Node"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + subscriptionInstanceTypeErrorSourcePropEnum = append(subscriptionInstanceTypeErrorSourcePropEnum, v) + } +} + +const ( + + // SubscriptionInstanceErrorSourceNone captures enum value "None" + SubscriptionInstanceErrorSourceNone string = "None" + + // SubscriptionInstanceErrorSourceSUBMGR captures enum value "SUBMGR" + SubscriptionInstanceErrorSourceSUBMGR string = "SUBMGR" + + // SubscriptionInstanceErrorSourceRTMGR captures enum value "RTMGR" + SubscriptionInstanceErrorSourceRTMGR string = "RTMGR" + + // SubscriptionInstanceErrorSourceDBAAS captures enum value "DBAAS" + SubscriptionInstanceErrorSourceDBAAS string = "DBAAS" + + // SubscriptionInstanceErrorSourceASN1 captures enum value "ASN1" + SubscriptionInstanceErrorSourceASN1 string = "ASN1" + + // SubscriptionInstanceErrorSourceE2Node captures enum value "E2Node" + SubscriptionInstanceErrorSourceE2Node string = "E2Node" +) + +// prop value enum +func (m *SubscriptionInstance) validateErrorSourceEnum(path, location string, value string) error { + if err := validate.Enum(path, location, value, subscriptionInstanceTypeErrorSourcePropEnum); err != nil { + return err + } + return nil +} + +func (m *SubscriptionInstance) validateErrorSource(formats strfmt.Registry) error { + + if err := validate.Required("ErrorSource", "body", m.ErrorSource); err != nil { + return err + } + + // value enum + if err := m.validateErrorSourceEnum("ErrorSource", "body", *m.ErrorSource); err != nil { + return err + } + + return nil +} + +var subscriptionInstanceTypeRejectCausePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["None","REST-subscription-ongoing","REST-subscription-delete-ongoing","Invalid-REST-request-message","REST-subscription-with-given-id-does-not-exist","E2-interface-down","Other"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + subscriptionInstanceTypeRejectCausePropEnum = append(subscriptionInstanceTypeRejectCausePropEnum, v) + } +} + +const ( + + // SubscriptionInstanceRejectCauseNone captures enum value "None" + SubscriptionInstanceRejectCauseNone string = "None" + + // SubscriptionInstanceRejectCauseRESTSubscriptionOngoing captures enum value "REST-subscription-ongoing" + SubscriptionInstanceRejectCauseRESTSubscriptionOngoing string = "REST-subscription-ongoing" + + // SubscriptionInstanceRejectCauseRESTSubscriptionDeleteOngoing captures enum value "REST-subscription-delete-ongoing" + SubscriptionInstanceRejectCauseRESTSubscriptionDeleteOngoing string = "REST-subscription-delete-ongoing" + + // SubscriptionInstanceRejectCauseInvalidRESTRequestMessage captures enum value "Invalid-REST-request-message" + SubscriptionInstanceRejectCauseInvalidRESTRequestMessage string = "Invalid-REST-request-message" + + // SubscriptionInstanceRejectCauseRESTSubscriptionWithGivenIDDoesNotExist captures enum value "REST-subscription-with-given-id-does-not-exist" + SubscriptionInstanceRejectCauseRESTSubscriptionWithGivenIDDoesNotExist string = "REST-subscription-with-given-id-does-not-exist" + + // SubscriptionInstanceRejectCauseE2InterfaceDown captures enum value "E2-interface-down" + SubscriptionInstanceRejectCauseE2InterfaceDown string = "E2-interface-down" + + // SubscriptionInstanceRejectCauseOther captures enum value "Other" + SubscriptionInstanceRejectCauseOther string = "Other" +) + +// prop value enum +func (m *SubscriptionInstance) validateRejectCauseEnum(path, location string, value string) error { + if err := validate.Enum(path, location, value, subscriptionInstanceTypeRejectCausePropEnum); err != nil { + return err + } + return nil +} + +func (m *SubscriptionInstance) validateRejectCause(formats strfmt.Registry) error { + + if swag.IsZero(m.RejectCause) { // not required + return nil + } + + // value enum + if err := m.validateRejectCauseEnum("RejectCause", "body", *m.RejectCause); err != nil { + return err + } + + return nil +} + +var subscriptionInstanceTypeTimeoutTypePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["None","E2-Timeout","RTMGR-Timeout","DBAAS-Timeout"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + subscriptionInstanceTypeTimeoutTypePropEnum = append(subscriptionInstanceTypeTimeoutTypePropEnum, v) + } +} + +const ( + + // SubscriptionInstanceTimeoutTypeNone captures enum value "None" + SubscriptionInstanceTimeoutTypeNone string = "None" + + // SubscriptionInstanceTimeoutTypeE2Timeout captures enum value "E2-Timeout" + SubscriptionInstanceTimeoutTypeE2Timeout string = "E2-Timeout" + + // SubscriptionInstanceTimeoutTypeRTMGRTimeout captures enum value "RTMGR-Timeout" + SubscriptionInstanceTimeoutTypeRTMGRTimeout string = "RTMGR-Timeout" + + // SubscriptionInstanceTimeoutTypeDBAASTimeout captures enum value "DBAAS-Timeout" + SubscriptionInstanceTimeoutTypeDBAASTimeout string = "DBAAS-Timeout" +) + +// prop value enum +func (m *SubscriptionInstance) validateTimeoutTypeEnum(path, location string, value string) error { + if err := validate.Enum(path, location, value, subscriptionInstanceTypeTimeoutTypePropEnum); err != nil { + return err + } + return nil +} + +func (m *SubscriptionInstance) validateTimeoutType(formats strfmt.Registry) error { + + if err := validate.Required("TimeoutType", "body", m.TimeoutType); err != nil { + return err + } + + // value enum + if err := m.validateTimeoutTypeEnum("TimeoutType", "body", *m.TimeoutType); err != nil { + return err + } + + return nil +} + func (m *SubscriptionInstance) validateXappEventInstanceID(formats strfmt.Registry) error { if err := validate.Required("XappEventInstanceId", "body", m.XappEventInstanceID); err != nil { diff --git a/pkg/models/subscription_params.go b/pkg/models/subscription_params.go index 5616e98..a7151d5 100644 --- a/pkg/models/subscription_params.go +++ b/pkg/models/subscription_params.go @@ -21,6 +21,9 @@ type SubscriptionParams struct { // Required: true ClientEndpoint *SubscriptionParamsClientEndpoint `json:"ClientEndpoint"` + // e2 subscription directives + E2SubscriptionDirectives *SubscriptionParamsE2SubscriptionDirectives `json:"E2SubscriptionDirectives,omitempty"` + // meid // Required: true Meid *string `json:"Meid"` @@ -47,6 +50,10 @@ func (m *SubscriptionParams) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateE2SubscriptionDirectives(formats); err != nil { + res = append(res, err) + } + if err := m.validateMeid(formats); err != nil { res = append(res, err) } @@ -83,6 +90,24 @@ func (m *SubscriptionParams) validateClientEndpoint(formats strfmt.Registry) err return nil } +func (m *SubscriptionParams) validateE2SubscriptionDirectives(formats strfmt.Registry) error { + + if swag.IsZero(m.E2SubscriptionDirectives) { // not required + return nil + } + + if m.E2SubscriptionDirectives != nil { + if err := m.E2SubscriptionDirectives.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("E2SubscriptionDirectives") + } + return err + } + } + + return nil +} + func (m *SubscriptionParams) validateMeid(formats strfmt.Registry) error { if err := validate.Required("Meid", "body", m.Meid); err != nil { @@ -231,3 +256,92 @@ func (m *SubscriptionParamsClientEndpoint) UnmarshalBinary(b []byte) error { *m = res return nil } + +// SubscriptionParamsE2SubscriptionDirectives subscription params e2 subscription directives +// +// swagger:model SubscriptionParamsE2SubscriptionDirectives +type SubscriptionParamsE2SubscriptionDirectives struct { + + // How many times E2 subscription request is retried + // Maximum: 10 + // Minimum: 0 + E2RetryCount *int64 `json:"E2RetryCount,omitempty"` + + // How long time response is waited from E2 node + // Maximum: 10 + // Minimum: 1 + E2TimeoutTimerValue int64 `json:"E2TimeoutTimerValue,omitempty"` + + // Subscription needs RMR route from E2Term to xApp + RMRRoutingNeeded *bool `json:"RMRRoutingNeeded,omitempty"` +} + +// Validate validates this subscription params e2 subscription directives +func (m *SubscriptionParamsE2SubscriptionDirectives) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateE2RetryCount(formats); err != nil { + res = append(res, err) + } + + if err := m.validateE2TimeoutTimerValue(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *SubscriptionParamsE2SubscriptionDirectives) validateE2RetryCount(formats strfmt.Registry) error { + + if swag.IsZero(m.E2RetryCount) { // not required + return nil + } + + if err := validate.MinimumInt("E2SubscriptionDirectives"+"."+"E2RetryCount", "body", int64(*m.E2RetryCount), 0, false); err != nil { + return err + } + + if err := validate.MaximumInt("E2SubscriptionDirectives"+"."+"E2RetryCount", "body", int64(*m.E2RetryCount), 10, false); err != nil { + return err + } + + return nil +} + +func (m *SubscriptionParamsE2SubscriptionDirectives) validateE2TimeoutTimerValue(formats strfmt.Registry) error { + + if swag.IsZero(m.E2TimeoutTimerValue) { // not required + return nil + } + + if err := validate.MinimumInt("E2SubscriptionDirectives"+"."+"E2TimeoutTimerValue", "body", int64(m.E2TimeoutTimerValue), 1, false); err != nil { + return err + } + + if err := validate.MaximumInt("E2SubscriptionDirectives"+"."+"E2TimeoutTimerValue", "body", int64(m.E2TimeoutTimerValue), 10, false); err != nil { + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *SubscriptionParamsE2SubscriptionDirectives) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *SubscriptionParamsE2SubscriptionDirectives) UnmarshalBinary(b []byte) error { + var res SubscriptionParamsE2SubscriptionDirectives + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/pkg/xapp/subscription.go b/pkg/xapp/subscription.go index efaf0f8..01e351f 100755 --- a/pkg/xapp/subscription.go +++ b/pkg/xapp/subscription.go @@ -44,9 +44,9 @@ import ( "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/common" ) -type SubscriptionHandler func(interface{}) (*models.SubscriptionResponse, error) +type SubscriptionHandler func(interface{}) (*models.SubscriptionResponse, int) type SubscriptionQueryHandler func() (models.SubscriptionList, error) -type SubscriptionDeleteHandler func(string) error +type SubscriptionDeleteHandler func(string) int type SubscriptionResponseCallback func(*apimodel.SubscriptionResponse) type Subscriber struct { @@ -121,20 +121,30 @@ func (r *Subscriber) Listen(createSubscription SubscriptionHandler, getSubscript api.CommonSubscribeHandler = common.SubscribeHandlerFunc( func(params common.SubscribeParams) middleware.Responder { Logger.Error("Subscribe: Params=%+v", params.SubscriptionParams) - if resp, err := createSubscription(params.SubscriptionParams); err == nil { - return common.NewSubscribeCreated().WithPayload(resp) + resp, retCode := createSubscription(params.SubscriptionParams) + if retCode != common.SubscribeCreatedCode { + if retCode == common.SubscribeBadRequestCode { + return common.NewSubscribeBadRequest() + } else { + return common.NewSubscribeInternalServerError() + } } - return common.NewSubscribeInternalServerError() + return common.NewSubscribeCreated().WithPayload(resp) }) // Subscription: Unsubscribe api.CommonUnsubscribeHandler = common.UnsubscribeHandlerFunc( func(p common.UnsubscribeParams) middleware.Responder { Logger.Error("Unsubscribe: SubscriptionID=%+v", p.SubscriptionID) - if err := delSubscription(p.SubscriptionID); err == nil { - return common.NewUnsubscribeNoContent() + retCode := delSubscription(p.SubscriptionID) + if retCode != common.UnsubscribeNoContentCode { + if retCode == common.UnsubscribeBadRequestCode { + return common.NewUnsubscribeBadRequest() + } else { + return common.NewUnsubscribeInternalServerError() + } } - return common.NewUnsubscribeInternalServerError() + return common.NewUnsubscribeNoContent() }) server := restapi.NewServer(api) diff --git a/pkg/xapp/subscription_test.go b/pkg/xapp/subscription_test.go index af8938c..d41649f 100755 --- a/pkg/xapp/subscription_test.go +++ b/pkg/xapp/subscription_test.go @@ -16,6 +16,7 @@ import ( "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientmodel" "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models" + "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/common" "github.com/stretchr/testify/assert" ) @@ -58,29 +59,7 @@ func TestSubscriptionQueryHandling(t *testing.T) { } func TestSubscriptionHandling(t *testing.T) { - subscriptionParams := clientmodel.SubscriptionParams{ - SubscriptionID: "", - Meid: &meid, - RANFunctionID: &funId, - ClientEndpoint: &clientEndpoint, - SubscriptionDetails: clientmodel.SubscriptionDetailsList{ - &clientmodel.SubscriptionDetail{ - XappEventInstanceID: &eventInstanceId, - EventTriggers: clientmodel.EventTriggerDefinition{00, 0x11, 0x12, 0x13, 0x00, 0x21, 0x22, 0x24, 0x1B, 0x80}, - ActionToBeSetupList: clientmodel.ActionsToBeSetup{ - &clientmodel.ActionToBeSetup{ - ActionID: &actionId, - ActionType: &actionType, - ActionDefinition: clientmodel.ActionDefinition{5, 6, 7, 8}, - SubsequentAction: &clientmodel.SubsequentAction{ - SubsequentActionType: &subsequestActioType, - TimeToWait: &timeToWait, - }, - }, - }, - }, - }, - } + subscriptionParams := GetSubscriptionparams() Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) { assert.Equal(t, len(resp.SubscriptionInstances), 1) @@ -88,13 +67,57 @@ func TestSubscriptionHandling(t *testing.T) { assert.Equal(t, *resp.SubscriptionInstances[0].E2EventInstanceID, int64(22)) }) - _, err := Subscription.Subscribe(&subscriptionParams) + _, err := Subscription.Subscribe(subscriptionParams) assert.Equal(t, err, nil) } func TestSubscriptionWithClientProvidedIdHandling(t *testing.T) { - subscriptionParams := clientmodel.SubscriptionParams{ - SubscriptionID: "myxapp", + subscriptionParams := GetSubscriptionparams() + subscriptionParams.SubscriptionID = "myxapp" + + Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) { + assert.Equal(t, len(resp.SubscriptionInstances), 1) + assert.Equal(t, *resp.SubscriptionInstances[0].XappEventInstanceID, int64(11)) + assert.Equal(t, *resp.SubscriptionInstances[0].E2EventInstanceID, int64(22)) + }) + + _, err := Subscription.Subscribe(subscriptionParams) + assert.Equal(t, err, nil) +} + +func TestBadRequestSubscriptionHandling(t *testing.T) { + subscriptionParams := GetSubscriptionparams() + subscriptionParams.SubscriptionID = "123_send_bad_request_response" + + Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) { + assert.Equal(t, len(resp.SubscriptionInstances), 1) + assert.Equal(t, *resp.SubscriptionInstances[0].XappEventInstanceID, int64(11)) + assert.Equal(t, *resp.SubscriptionInstances[0].E2EventInstanceID, int64(22)) + }) + + _, err := Subscription.Subscribe(subscriptionParams) + assert.Equal(t, err.Error(), "[POST /subscriptions][400] subscribeBadRequest ") + fmt.Println("Error:",err) +} + +func TestInternalServerErrorSubscriptionHandling(t *testing.T) { + subscriptionParams := GetSubscriptionparams() + subscriptionParams.SubscriptionID = "123_send_internal_server_error_response" + + Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) { + assert.Equal(t, len(resp.SubscriptionInstances), 1) + assert.Equal(t, *resp.SubscriptionInstances[0].XappEventInstanceID, int64(11)) + assert.Equal(t, *resp.SubscriptionInstances[0].E2EventInstanceID, int64(22)) + }) + + _, err := Subscription.Subscribe(subscriptionParams) + assert.Equal(t, err.Error(), "[POST /subscriptions][500] subscribeInternalServerError ") + fmt.Println("Error:",err) +} + +func GetSubscriptionparams() *clientmodel.SubscriptionParams { + return &clientmodel.SubscriptionParams{ + SubscriptionID: "", Meid: &meid, RANFunctionID: &funId, ClientEndpoint: &clientEndpoint, @@ -116,21 +139,29 @@ func TestSubscriptionWithClientProvidedIdHandling(t *testing.T) { }, }, } +} - Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) { - assert.Equal(t, len(resp.SubscriptionInstances), 1) - assert.Equal(t, *resp.SubscriptionInstances[0].XappEventInstanceID, int64(11)) - assert.Equal(t, *resp.SubscriptionInstances[0].E2EventInstanceID, int64(22)) - }) - - _, err := Subscription.Subscribe(&subscriptionParams) +func TestSuccessfulSubscriptionDeleteHandling(t *testing.T) { + subscriptionId = "123_send_successful_response" + err := Subscription.Unsubscribe(subscriptionId) assert.Equal(t, err, nil) + fmt.Println("Error:",err) } -func TestSubscriptionDeleteHandling(t *testing.T) { +func TestBadRequestSubscriptionDeleteHandling(t *testing.T) { + subscriptionId = "123_send_bad_request_response" err := Subscription.Unsubscribe(subscriptionId) - fmt.Println(err) - assert.Equal(t, err, nil) + assert.NotEqual(t, err, nil) + fmt.Println("Error:",err.Error()) + assert.Equal(t, err.Error(), "[DELETE /subscriptions/{subscriptionId}][400] unsubscribeBadRequest ") +} + +func TestInternalServerErrorSubscriptionDeleteHandling(t *testing.T) { + subscriptionId = "123_send_internal_server_error_response" + err := Subscription.Unsubscribe(subscriptionId) + assert.NotEqual(t, err, nil) + fmt.Println("Error:",err.Error()) + assert.Equal(t, err.Error(), "[DELETE /subscriptions/{subscriptionId}][500] unsubscribeInternalServerError ") } func TestResponseHandler(t *testing.T) { @@ -175,7 +206,7 @@ func processSubscriptions(subscriptionId string) { Subscription.Notify(resp, models.SubscriptionParamsClientEndpoint{Host: "localhost", HTTPPort: &hPort, RMRPort: &rPort}) } -func subscriptionHandler(params interface{}) (*models.SubscriptionResponse, error) { +func subscriptionHandler(params interface{}) (*models.SubscriptionResponse, int) { p := params.(*models.SubscriptionParams) assert.Equal(suite, meid, *p.Meid) @@ -197,13 +228,25 @@ func subscriptionHandler(params interface{}) (*models.SubscriptionResponse, erro // Generate a unique subscriptionId subscriptionId = fmt.Sprintf("%s-%s", meid, clientEndpoint.Host) + if p.SubscriptionID == "123_send_bad_request_response" { + // Simulate bad request case + return &models.SubscriptionResponse{ + }, common.UnsubscribeBadRequestCode + + } + + if p.SubscriptionID == "123_send_internal_server_error_response" { + // Simulate bad internal server error case + return &models.SubscriptionResponse{ + }, common.UnsubscribeInternalServerErrorCode + } // Process subscriptions on the background go processSubscriptions(subscriptionId) // and send response immediately return &models.SubscriptionResponse{ SubscriptionID: &subscriptionId, - }, nil + }, common.SubscribeCreatedCode } func queryHandler() (models.SubscriptionList, error) { @@ -217,7 +260,13 @@ func queryHandler() (models.SubscriptionList, error) { return resp, nil } -func deleteHandler(ep string) error { +func deleteHandler(ep string) int { assert.Equal(suite, subscriptionId, ep) - return nil + if subscriptionId == "123_send_successful_response" { + return common.UnsubscribeNoContentCode + } else if subscriptionId == "123_send_bad_request_response" { + return common.UnsubscribeBadRequestCode + } else { + return common.UnsubscribeInternalServerErrorCode + } }