Commit 4a18e806 authored by Ikram Haq's avatar Ikram Haq
Browse files

Add PATCH method to update the newly created service

parent 3b641715
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -47,6 +47,10 @@ func AppServicesServiceIdPUT(w http.ResponseWriter, r *http.Request) {
	appServicesByIdPUT(w, r)
}

func AppServicesServiceIdPATCH(w http.ResponseWriter, r *http.Request) {
	appServicesByIdPATCH(w, r)
}

func ApplicationsSubscriptionDELETE(w http.ResponseWriter, r *http.Request) {
	applicationsSubscriptionDELETE(w, r)
}
+9 −0
Original line number Diff line number Diff line
@@ -40,6 +40,15 @@ func convertServiceInfoToJson_1(obj *ServiceApiDescription) string {
	return string(jsonInfo)
}

func convertServiceInfoToJson_2(obj *ServiceApiDescriptionPatch) string {
	jsonInfo, err := json.Marshal(*obj)
	if err != nil {
		log.Error(err.Error())
		return ""
	}
	return string(jsonInfo)
}

func convertJsonToServiceInfo(jsonInfo string) *ServiceInfo {
	var obj ServiceInfo
	err := json.Unmarshal([]byte(jsonInfo), &obj)
+24 −0
Original line number Diff line number Diff line
/*
 * MEC service management realized by CAPIF APIs
 *
 * The ETSI MEC ISG MEC011 MEC Service Management realized by CAPIF APIs described using OpenAPI
 *
 * API version: 3.2.1
 * Contact: cti_support@etsi.org
 * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
 */
package server

type MecServiceInfoCapifExtPatch struct {
	Serializer *SerializerType `json:"serializer,omitempty"`

	State *ServiceState `json:"state,omitempty"`

	ScopeOfLocality *LocalityType `json:"scopeOfLocality,omitempty"`

	ConsumedLocalOnly bool `json:"consumedLocalOnly,omitempty"`

	IsLocal bool `json:"isLocal,omitempty"`

	Category *CategoryRef `json:"category,omitempty"`
}
+14 −0
Original line number Diff line number Diff line
/*
 * MEC service management realized by CAPIF APIs
 *
 * The ETSI MEC ISG MEC011 MEC Service Management realized by CAPIF APIs described using OpenAPI
 *
 * API version: 3.2.1
 * Contact: cti_support@etsi.org
 * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
 */
package server

type ServiceApiDescriptionPatch struct {
	VendorSpecificUrnetsimeccapifextserviceInfo *MecServiceInfoCapifExtPatch `json:"vendorSpecific-urn:etsi:mec:capifext:service-info,omitempty"`
}
+159 −0
Original line number Diff line number Diff line
@@ -570,6 +570,165 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, convertServiceInfoToJson_1(dsInfo))
}

func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	log.Info("appServicesByIdPUT")
	vars := mux.Vars(r)
	svcId := vars["serviceApiId"]
	appId := vars["apfId"]

	mutex.Lock()
	defer mutex.Unlock()

	// Get App instance
	appInfo, err := getAppInfo(appId)
	if err != nil {
		errHandlerProblemDetails(w, err.Error(), http.StatusNotFound)
		return
	}

	// Validate App info
	code, problemDetails, err := validateAppInfo(appInfo)
	if err != nil {
		log.Error(err.Error())
		if problemDetails != "" {
			w.WriteHeader(code)
			fmt.Fprint(w, problemDetails)
		} else {
			errHandlerProblemDetails(w, err.Error(), code)
		}
		return
	}

	// Get previous service info
	sInfoPrevJson, err := getServiceById(appId, svcId)
	if err != nil {
		log.Error(err.Error())
		w.WriteHeader(http.StatusNotFound)
		return
	}
	sInfoPrev := convertJsonToServiceInfo(sInfoPrevJson)

	// Retrieve request parameters from body
	if r.Body == nil {
		err := errors.New("Request body is missing")
		errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest)
		return
	}
	// NOTE: Set default values for omitted fields
	locality := MEC_HOST_LocalityType
	sInfo := ServiceApiDescriptionPatch{
		VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExtPatch{
			ScopeOfLocality:   &locality,
			IsLocal:           true,
			ConsumedLocalOnly: true,
		},
	}
	decoder := json.NewDecoder(r.Body)
	err = decoder.Decode(&sInfo)
	if err != nil {
		log.Error(err.Error())
		errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// aefProfile := &AefProfile{
	// 	AefId:                 sInfo.AefProfiles[0].AefId,
	// 	Versions:              sInfo.AefProfiles[0].Versions,
	// 	InterfaceDescriptions: sInfo.AefProfiles[0].InterfaceDescriptions,
	// 	VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{
	// 		Name:     sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Name,
	// 		Type_:    sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Type_,
	// 		Protocol: sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Protocol,
	// 		Version:  sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Version,
	// 		Security: sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Security,
	// 	},
	// }
	dsInfo := &ServiceApiDescriptionPatch{
		// ApiName:     sInfo.ApiName,
		// ApiId:       sInfo.ApiId,
		// AefProfiles: []AefProfile{*aefProfile},
		VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExtPatch{
			Serializer:        sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer,
			State:             sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State,
			ScopeOfLocality:   sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality,
			ConsumedLocalOnly: sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly,
			IsLocal:           sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.IsLocal,
			Category:          sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category,
		},
	}

	// transportInfo_ := TransportInfo{
	// 	Id:       sInfo.AefProfiles[0].AefId,
	// 	Name:     sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Name,
	// 	Type_:    sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Type_,
	// 	Protocol: sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Protocol,
	// 	Version:  sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Version,
	// 	Endpoint: sInfo.AefProfiles[0].InterfaceDescriptions,
	// 	Security: sInfo.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Security,
	// }

	// Create Service
	_sInfo := ServiceInfo{
		SerCategory:       dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category,
		State:             dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State,
		Serializer:        dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer,
		ScopeOfLocality:   dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality,
		ConsumedLocalOnly: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly,
		IsLocal:           dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.IsLocal,
		LivenessInterval:  0,
	}

	// Current implementation only supports state parameter change;
	// Make sure none of the other service information fields have changed
	state := *_sInfo.State
	*_sInfo.State = *sInfoPrev.State
	// isLocal is only set in responses, subscriptions and notifications;
	// Ignore this field while comparing the previous & new service info structs
	_sInfo.IsLocal = sInfoPrev.IsLocal

	// Compare service information as JSON strings
	/* FSCOM: It is not specified that only the ServiceInfo state property may be changed in ETSI GS MEC 011 V3.2.1 (2024-04)
	sInfoJson := convertServiceInfoToJson(&sInfo)
	if sInfoJson != sInfoPrevJson {
		errStr := "Only the ServiceInfo state property may be changed"
		log.Error(errStr)
		errHandlerProblemDetails(w, errStr, http.StatusBadRequest)
		return
	}*/

	// Compare service info states & update DB if necessary
	*_sInfo.State = state
	if *_sInfo.State != *sInfoPrev.State {
		err, retCode := setService(appId, &_sInfo, STATE_CHANGED_ServiceAvailabilityNotificationChangeType)
		if err != nil {
			log.Error(err.Error())
			errHandlerProblemDetails(w, err.Error(), retCode)
			return
		}
	}

	// Compare LivenessInterval
	if _sInfo.LivenessInterval != sInfoPrev.LivenessInterval {
		if _, ok := livenessTimerList[_sInfo.SerInstanceId]; ok { // An entry already exist
			if _sInfo.LivenessInterval != 0 { // update it
				updateLivenessTicker(_sInfo)
			} else {
				deleteLivenessTicker(_sInfo.SerInstanceId)
			}
		} else { // No entry
			if _sInfo.LivenessInterval != 0 { // Create a new entry
				createLivenessTicker(_sInfo)
			}
		}
	} // else, nothing to do
	_sInfo.LivenessInterval = sInfoPrev.LivenessInterval

	// Send response
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, convertServiceInfoToJson_2(dsInfo))
}

func appServicesByIdDELETE(w http.ResponseWriter, r *http.Request) {
	log.Info("appServicesByIdDELETE")
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Loading