From 392e882d4baa49800fa33ae15272f6294ddd6d13 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 1 Aug 2024 10:40:13 +0000 Subject: [PATCH 01/43] Add new serive CAPIF mgmt, update client side packages and implement GET method to get the all services --- .../api/capif-mgmt/swagger.yaml | 1383 +++++++++++++ .../server/app-enablement.go | 13 + .../server/capif-mgmt/README.md | 25 + .../server/capif-mgmt/api_mec_service_mgmt.go | 84 + .../server/capif-mgmt/convert.go | 115 ++ .../model_app_instance_id_services_body.go | 14 + .../server/capif-mgmt/model_category_ref.go | 22 + .../model_end_point_info_address.go | 18 + .../model_end_point_info_addresses.go | 16 + .../model_end_point_info_alternative.go | 16 + .../capif-mgmt/model_end_point_info_fqdn.go | 16 + .../capif-mgmt/model_end_point_info_uris.go | 16 + .../server/capif-mgmt/model_link_type.go | 16 + .../server/capif-mgmt/model_locality_type.go | 24 + .../model_mec_service_info_capif_ext.go | 24 + ...service_mgmt_api_subscription_link_list.go | 15 + ...e_mgmt_api_subscription_link_list_links.go | 17 + ...api_subscription_link_list_subscription.go | 18 + .../model_one_of_transport_info_endpoint.go | 17 + ...del_one_ofapp_instance_id_services_body.go | 13 + .../capif-mgmt/model_problem_details.go | 23 + .../server/capif-mgmt/model_security_info.go | 15 + .../model_security_info_o_auth2_info.go | 18 + ...l_security_info_o_auth2_info_grant_type.go | 21 + .../server/capif-mgmt/model_self.go | 15 + ..._availability_notification_subscription.go | 21 + ...ication_subscription_filtering_criteria.go | 24 + .../capif-mgmt/model_serializer_type.go | 20 + .../model_service_api_description.go | 19 + ...model_service_availability_notification.go | 20 + ...e_availability_notification_change_type.go | 22 + ...ability_notification_service_references.go | 23 + .../server/capif-mgmt/model_service_info.go | 40 + .../capif-mgmt/model_service_info__links.go | 16 + .../capif-mgmt/model_service_liveness_info.go | 18 + .../model_service_liveness_info_time_stamp.go | 17 + .../model_service_liveness_update.go | 14 + .../server/capif-mgmt/model_service_state.go | 20 + .../server/capif-mgmt/model_subscription.go | 15 + .../model_subscription_link_list.go | 29 + .../model_subscription_link_list__links.go | 31 + ...cription_link_list__links_subscriptions.go | 32 + .../server/capif-mgmt/model_transport_info.go | 32 + .../server/capif-mgmt/model_transport_type.go | 25 + .../server/capif-mgmt/service-mgmt.go | 1796 +++++++++++++++++ go-apps/meep-app-enablement/server/routers.go | 13 + .../server/service-mgmt/service-mgmt.go | 2 +- go-packages/meep-capif-mgmt-client/.gitignore | 24 + .../.swagger-codegen-ignore | 23 + .../.swagger-codegen/VERSION | 1 + .../meep-capif-mgmt-client/.travis.yml | 8 + go-packages/meep-capif-mgmt-client/README.md | 59 + .../meep-capif-mgmt-client/api/swagger.yaml | 1386 +++++++++++++ .../meep-capif-mgmt-client/api_services.go | 1272 ++++++++++++ go-packages/meep-capif-mgmt-client/client.go | 478 +++++ .../meep-capif-mgmt-client/configuration.go | 72 + .../docs/AppServicesApi.md | 188 ++ .../docs/AppSubscriptionsApi.md | 129 ++ .../meep-capif-mgmt-client/docs/CapifEvent.md | 8 + .../docs/CategoryRef.md | 12 + .../docs/DiscoveredApis.md | 9 + .../docs/EventNotification.md | 9 + .../docs/EventSubscription.md | 12 + .../docs/EventSubscriptionPatch.md | 10 + .../docs/LocalityType.md | 8 + .../docs/MecServiceInfoCapifExt.md | 14 + .../docs/MecServiceInfoCapifExtPatch.md | 14 + .../docs/ProblemDetails.md | 13 + .../docs/SerializerType.md | 8 + .../docs/ServiceApiDescription.md | 11 + .../docs/ServiceApiDescriptionPatch.md | 9 + .../docs/ServiceState.md | 8 + .../docs/ServicesApi.md | 48 + .../meep-capif-mgmt-client/git_push.sh | 52 + .../model_capif_event.go | 20 + .../model_category_ref.go | 22 + .../model_discovered_apis.go | 14 + .../model_event_notification.go | 15 + .../model_event_subscription.go | 18 + .../model_event_subscription_patch.go | 17 + .../model_locality_type.go | 23 + .../model_mec_service_info_capif_ext.go | 19 + .../model_mec_service_info_capif_ext_patch.go | 19 + .../model_problem_details.go | 23 + .../model_serializer_type.go | 20 + .../model_service_api_description.go | 18 + .../model_service_api_description_patch.go | 14 + .../model_service_state.go | 20 + .../meep-capif-mgmt-client/response.go | 43 + 89 files changed, 8412 insertions(+), 1 deletion(-) create mode 100644 go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/README.md create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/convert.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_app_instance_id_services_body.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_category_ref.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_address.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_addresses.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_alternative.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_fqdn.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_uris.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_link_type.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_locality_type.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_links.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_subscription.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_one_of_transport_info_endpoint.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_one_ofapp_instance_id_services_body.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_problem_details.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_security_info.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info_grant_type.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_self.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription_filtering_criteria.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_serializer_type.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_change_type.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_info.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_info__links.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info_time_stamp.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_update.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_state.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_subscription.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links_subscriptions.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_transport_info.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_transport_type.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go create mode 100644 go-packages/meep-capif-mgmt-client/.gitignore create mode 100644 go-packages/meep-capif-mgmt-client/.swagger-codegen-ignore create mode 100644 go-packages/meep-capif-mgmt-client/.swagger-codegen/VERSION create mode 100644 go-packages/meep-capif-mgmt-client/.travis.yml create mode 100644 go-packages/meep-capif-mgmt-client/README.md create mode 100644 go-packages/meep-capif-mgmt-client/api/swagger.yaml create mode 100644 go-packages/meep-capif-mgmt-client/api_services.go create mode 100644 go-packages/meep-capif-mgmt-client/client.go create mode 100644 go-packages/meep-capif-mgmt-client/configuration.go create mode 100644 go-packages/meep-capif-mgmt-client/docs/AppServicesApi.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/AppSubscriptionsApi.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/CapifEvent.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/CategoryRef.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/DiscoveredApis.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/EventNotification.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/EventSubscription.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/EventSubscriptionPatch.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/LocalityType.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExt.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExtPatch.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/ProblemDetails.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/SerializerType.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/ServiceApiDescription.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/ServiceApiDescriptionPatch.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/ServiceState.md create mode 100644 go-packages/meep-capif-mgmt-client/docs/ServicesApi.md create mode 100644 go-packages/meep-capif-mgmt-client/git_push.sh create mode 100644 go-packages/meep-capif-mgmt-client/model_capif_event.go create mode 100644 go-packages/meep-capif-mgmt-client/model_category_ref.go create mode 100644 go-packages/meep-capif-mgmt-client/model_discovered_apis.go create mode 100644 go-packages/meep-capif-mgmt-client/model_event_notification.go create mode 100644 go-packages/meep-capif-mgmt-client/model_event_subscription.go create mode 100644 go-packages/meep-capif-mgmt-client/model_event_subscription_patch.go create mode 100644 go-packages/meep-capif-mgmt-client/model_locality_type.go create mode 100644 go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext.go create mode 100644 go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext_patch.go create mode 100644 go-packages/meep-capif-mgmt-client/model_problem_details.go create mode 100644 go-packages/meep-capif-mgmt-client/model_serializer_type.go create mode 100644 go-packages/meep-capif-mgmt-client/model_service_api_description.go create mode 100644 go-packages/meep-capif-mgmt-client/model_service_api_description_patch.go create mode 100644 go-packages/meep-capif-mgmt-client/model_service_state.go create mode 100644 go-packages/meep-capif-mgmt-client/response.go diff --git a/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml b/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml new file mode 100644 index 000000000..a08ba68fc --- /dev/null +++ b/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml @@ -0,0 +1,1383 @@ +openapi: 3.0.0 +info: + title: MEC service management realized by CAPIF APIs + description: The ETSI MEC ISG MEC011 MEC Service Management realized by CAPIF APIs + described using OpenAPI + contact: + email: cti_support@etsi.org + license: + name: BSD-3-Clause + url: https://forge.etsi.org/legal-matters + version: 3.2.1 +externalDocs: + description: "ETSI GS MEC011 Application Enablement API, V3.2.1" + url: https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/03.02.01_60/gs_mec011v030201p.pdf +servers: +- url: https://localhost/sandboxname/service-apis/v1 + description: Service APIs +- url: https://localhost/sandboxname/published-apis/v1 + description: Published APIs +- url: https://localhost/sandboxname/capif-events/v1 + description: CAPIF Events APIs +tags: +- name: services +- name: appServices +- name: appSubscriptions +- name: callbacks +paths: + /allServiceAPIs: + get: + tags: + - services + description: This method retrieves information about a list of mecService resources. + This method is typically used in "service availability query" procedure + operationId: Services_GET + parameters: + - name: vend-spec-etsi-mec-serinstance-id + in: query + description: Vendor-specific query parameter for service instance ID. The + "target" attribute shall be set to "/apiId". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/apiId\", \"value\": \"serviceInstanceId\"}" + - name: api-name + in: query + description: "This query parameter corresponds to the parameter \"ser_name\"\ + \ as defined in clause 8.2.3.3.1. As opposed to the cardinality of ser_instance_id\ + \ defined in clause 8.2.3.3.1 that is 0..N, this parameter only supports\ + \ a cardinality of 0..1." + required: false + style: form + explode: true + schema: + type: array + items: + type: string + - name: api-invoker-id + in: query + description: "If the Discover_Service_API is produced by the MEC platform\ + \ towards the MEC applications, this identifier shall be set to the value\ + \ of the \"appInstanceId\" (see clause 7.1.2.6). If the Discover_Service_API\ + \ is produced by the CCF, the provisions in clause 8.1.2.2.3.1 of 3GPP TS\ + \ 29.222 [21] apply. " + required: false + style: form + explode: true + schema: + type: string + - name: vend-spec-etsi-mec-sercategory-id + in: query + description: Vendor-specific query parameter for service category ID. The + "target" attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id\"\ + , \"value\": \"serviceCategoryId\"}" + - name: vend-spec-etsi-mec-consumed-local-only + in: query + description: Vendor-specific query parameter for consumed local only. The + "target" attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly\"\ + , \"value\": \"true\"}" + - name: vend-spec-etsi-mec-is-local + in: query + description: Vendor-specific query parameter for is local. The "target" attribute + shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal\"\ + , \"value\": \"true\"}" + - name: vend-spec-etsi-mec-scope-of-locality + in: query + description: Vendor-specific query parameter for scope of locality. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality\"\ + , \"value\": \"scopeOfLocalityValue\"}" + responses: + "200": + description: | + The response body contains the result of the search over the list of registered APIs. + content: + application/json: + schema: + $ref: '#/components/schemas/DiscoveredAPIs' + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: Contains an alternative target URI of the resource located + in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: Contains an alternative target URI of the resource located + in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "414": + description: It is used to indicate that the server is refusing to process + the request because the request URI is longer than the server is willing + or able to process. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + servers: + - url: https://localhost/sandboxname/service-apis/v1 + /{apfId}/service-apis: + get: + tags: + - appServices + summary: get services + description: This method retrieves information about a list of mecService resources. + This method is typically used in "service availability query" procedure + operationId: AppServices_GET + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + responses: + "200": + description: | + Successful case. The representation(s) of the "Individual APF published API" resource(s) of the requested service API(s) shall be returned in the response body. If there are no active "Individual APF published API" resources at the CCF, an empty array is returned. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + post: + tags: + - appServices + summary: Publish a new API + description: Enables a service consumer to request to publish a new API at the + CCF. + operationId: AppServices_POST + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescription' + required: true + responses: + "201": + description: | + Successful case. The service API is successfully published. The URI of the created "Individual APF published API" resource shall be returned in an HTTP "Location" header. + headers: + Location: + description: | + Contains the URI of the newly created resource, according to the structure: {apiRoot}/published-apis//{apfId}/service-apis/{serviceApiId} + style: simple + explode: false + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescription' + servers: + - url: https://localhost/sandboxname/published-apis/v1 + /{apfId}/service-apis/{serviceApiId}: + get: + tags: + - appServices + description: The HTTP GET method allows a service consumer to retrieve an existing + "Individual APF published API" resource at the CCF. + operationId: AppServicesServiceId_GET + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + responses: + "200": + description: | + Successful case. The service API is successfully published and a representation of the created "Individual APF published API" resource shall be returned. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + put: + tags: + - appServices + description: The HTTP PUT method allows a service consumer to update an existing + "Individual APF published API" resource at the CCF. + operationId: AppServicesServiceId_PUT + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescription' + required: true + responses: + "200": + description: | + Successful case. The service API is successfully published and a representation of the created "Individual APF published API" resource shall be returned. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "204": + description: Successful case. The "Individual APF published API" resource + is successfully updated and no content is returned in the response body. + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "412": + description: "Precondition Failed. It is used when a condition has failed\ + \ during conditional requests, e.g. when using ETags to avoid write conflicts." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + delete: + tags: + - appServices + description: The HTTP DELETE method allows a service consumer to delete an existing + "Individual APF published API" resource at the CCF + operationId: AppServicesServiceId_DELETE + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + responses: + "204": + description: Successful case. The "Individual APF published API" resource + is successfully deleted. + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + patch: + tags: + - appServices + description: The HTTP PATCH method allows a service consumer to modify an existing + "Individual APF published API" resource at the CCF. + operationId: AppServicesServiceId_PATCH + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescriptionPatch' + required: true + responses: + "200": + description: "Successful case. The \"Individual APF published API\"\n resource\ + \ is successfully modified and a representation of \n the updated resource\ + \ shall be returned in the response \n body.\n" + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "204": + description: Successful case. The "Individual APF published API" resource + is successfully updated and no content is returned in the response body. + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "412": + description: "Precondition Failed. It is used when a condition has failed\ + \ during conditional requests, e.g. when using ETags to avoid write conflicts." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + servers: + - url: https://localhost/sandboxname/published-apis/v1 + /{subscriberId}/subscriptions: + post: + tags: + - appSubscriptions + summary: Create a new CAPIF Events Subscription + description: Create a new CAPIF Events Subscription resource. + operationId: ApplicationsSubscriptions_POST + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + required: true + responses: + "201": + description: | + CAPIF Events Subscription resource created successfully. The URI of the created resource shall be returned in the "Location" HTTP header + headers: + Location: + description: | + Contains the URI of the newly created resource, according to the structure: {apiRoot}/capif-events//{subscriberId}/subscriptions/{subscriptionId} + style: simple + explode: false + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + callbacks: + EventNotification: + '{$request.body#/callbackReference}': + post: + tags: + - callbacks + summary: Create callback + description: "The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE,\ + \ and SERVICE_API_UPDATE defined in the type \"CAPIFEvent\" shall\ + \ be supported. The remaining values of that type need not be supported." + operationId: EventNotification_POST + requestBody: + $ref: '#/components/requestBodies/EventNotification' + responses: + "204": + description: ' The receipt of the Notification is acknowledged.' + deprecated: false + servers: + - url: https://localhost/sandboxname/capif-events/v1 + '/{subscriberId}/subscriptions/{subscriptionId} ': + put: + tags: + - appSubscriptions + summary: The PUT method is used to update an existing subscription resource. + description: The susbcribing entity shall initiate the HTTP PUT request message + and the CAPIF core function shall respond to the message. + operationId: ApplicationsSubscriptions_PUT + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + - name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + required: true + responses: + "200": + description: "The event subscription was successfully updated, and a representation\ + \ of the updated resource is returned." + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + "204": + description: The event subscription was successfully updated and no content + is returned in the response body. + "307": + description: Temporary redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + "308": + description: Permanent redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + delete: + tags: + - appSubscriptions + summary: Delete an existing CAPIF Event Subscription + description: This endpoint deletes an existing CAPIF Event Subscription resource. + operationId: ApplicationsSubscription_DELETE + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + - name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + responses: + "204": + description: The individual CAPIF Events Subscription matching the subscriptionId + is deleted. + "307": + description: "Temporary redirection, during resource termination. The response\ + \ shall include a Location header field containing an alternative URI\ + \ of the resource located in an alternative CAPIF core function." + headers: + Location: + description: An alternative URI of the resource located in an alternative + CAPIF core function. + style: simple + explode: false + schema: + type: string + "308": + description: "Permanent redirection, during resource termination. The response\ + \ shall include a Location header field containing an alternative URI\ + \ of the resource located in an alternative CAPIF core function." + headers: + Location: + description: An alternative URI of the resource located in an alternative + CAPIF core function. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. The request was invalid or cannot be served. The + exact error should be explained in the error payload. + "401": + description: Unauthorized. The request requires user authentication. + "403": + description: Forbidden. The server understood the request but refuses to + authorize it. + "404": + description: Not Found. The server has not found anything matching the Request-URI. + "500": + description: Internal Server Error. The server encountered an unexpected + condition which prevented it from fulfilling the request. + patch: + tags: + - appSubscriptions + summary: Modify an existing CAPIF Event Subscription + description: This endpoint modifies an existing CAPIF Event Subscription resource. + operationId: ApplicationsSubscription_patch + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + - name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscriptionPatch' + required: true + responses: + "200": + description: The subscription was successfully modified and a representation + of the updated resource is returned in the response body. + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + "204": + description: The subscription was successfully modified and no content was + returned in the response body. + "307": + description: Temporary redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + "308": + description: Permanent redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + servers: + - url: https://localhost/sandboxname/capif-events/v1 +components: + schemas: + EventSubscriptionPatch: + required: + - events + type: object + properties: + events: + type: array + description: | + The events for which the subscription is modified. + items: + $ref: '#/components/schemas/CAPIFEvent' + notificationDestination: + type: string + description: | + URI to which notifications will be sent. Shall be set to the value of the "callbackReference" attribute in the "SerAvailabilityNotificationSubscription" structure. + format: uri + EventSubscription: + required: + - events + - notificationDestination + type: object + properties: + events: + type: array + items: + $ref: '#/components/schemas/CAPIFEvent' + notificationDestination: + type: string + description: | + URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response. + format: uri + requestTestNotification: + type: boolean + websocketNotifConfig: + type: string + example: + notificationDestination: http://example.com/aeiou + websocketNotifConfig: websocketNotifConfig + events: + - SERVICE_API_AVAILABLE + - SERVICE_API_AVAILABLE + requestTestNotification: true + CAPIFEvent: + type: string + description: | + The CAPIFEvent data type represents the type of events for which the subscription is made. + enum: + - SERVICE_API_AVAILABLE + - SERVICE_API_UNAVAILABLE + - SERVICE_API_UPDATE + CategoryRef: + required: + - href + - id + - name + - version + type: object + properties: + href: + type: string + description: Reference of the catalogue + format: uri + id: + type: string + description: Unique identifier of the category + name: + type: string + description: "Name of the category, example values include RNI, Location\ + \ & Bandwidth Management" + version: + type: string + description: Category version + description: This type represents the category reference + example: + name: name + href: http://example.com/aeiou + id: id + version: version + ProblemDetails: + required: + - detail + - status + type: object + properties: + type: + type: string + description: A URI reference according to IETF RFC 3986 that identifies + the problem type + format: uri + title: + type: string + description: "A short, human-readable summary of the problem type" + status: + type: integer + description: The HTTP status code for this occurrence of the problem + format: uint32 + detail: + type: string + description: A human-readable explanation specific to this occurrence of + the problem + instance: + type: string + description: A URI reference that identifies the specific occurrence of + the problem + format: uri + EventNotification: + type: object + properties: + events: + type: array + description: | + The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE, and SERVICE_API_UPDATE defined in the type "CAPIFEvent" shall be supported. The remaining values of that type need not be supported. + items: + $ref: '#/components/schemas/CAPIFEvent' + SerializerType: + type: string + description: | + The enumeration SerializerType represents types of serializers. This enumeration shall be extensible. + enum: + - JSON + - XML + - PROTOBUF3 + LocalityType: + type: string + description: | + The enumeration LocalityType represents types of locality. + enum: + - MEC_SYSTEM + - MEC_HOST + - NFVI_POP + - ZONE + - ZONE_GROUP + - NFVI_NODE + ServiceState: + type: string + description: | + The enumeration ServiceState represents possible states of a MEC service instance. + enum: + - ACTIVE + - INACTIVE + - SUSPENDED + DiscoveredAPIs: + type: object + properties: + serviceAPIDescriptions: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + example: + serviceAPIDescriptions: + - apiName: apiName + vendorSpecific-urn:etsi:mec:capifext:service-info: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + apiId: apiId + - apiName: apiName + vendorSpecific-urn:etsi:mec:capifext:service-info: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + apiId: apiId + ServiceAPIDescriptionPatch: + type: object + properties: + vendorSpecific-urn:etsi:mec:capifext:service-info: + $ref: '#/components/schemas/MecServiceInfoCapifExtPatch' + ServiceAPIDescription: + type: object + properties: + apiName: + type: string + description: | + Shall be set to the value of the "serName" attribute as defined in clause 8.1.2.2. + apiId: + type: string + description: | + If present, shall be set to the value of the "serInstanceId" attribute as defined in clause 8.1.2.2. + vendorSpecific-urn:etsi:mec:capifext:service-info: + $ref: '#/components/schemas/MecServiceInfoCapifExt' + example: + apiName: apiName + vendorSpecific-urn:etsi:mec:capifext:service-info: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + apiId: apiId + MecServiceInfoCapifExtPatch: + type: object + properties: + serializer: + $ref: '#/components/schemas/SerializerType' + state: + $ref: '#/components/schemas/ServiceState' + scopeOfLocality: + $ref: '#/components/schemas/LocalityType' + consumedLocalOnly: + type: boolean + isLocal: + type: boolean + category: + $ref: '#/components/schemas/CategoryRef' + MecServiceInfoCapifExt: + type: object + properties: + serializer: + $ref: '#/components/schemas/SerializerType' + state: + $ref: '#/components/schemas/ServiceState' + scopeOfLocality: + $ref: '#/components/schemas/LocalityType' + consumedLocalOnly: + type: boolean + isLocal: + type: boolean + category: + $ref: '#/components/schemas/CategoryRef' + example: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + responses: + "400": + description: Bad Request. It is used to indicate that incorrect parameters were + passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "401": + description: Unauthorized. It is used when the client did not submit the appropriate + credentials. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "409": + description: "Conflict. The operation cannot be executed currently, due to a\ + \ conflict with the state of the resource. Typically, this is because the\ + \ application instance resource is in NOT_INSTANTIATED state." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "412": + description: "Precondition Failed. It is used when a condition has failed during\ + \ conditional requests, e.g. when using ETags to avoid write conflicts." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "414": + description: It is used to indicate that the server is refusing to process the + request because the request URI is longer than the server is willing or able + to process. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "429": + description: Too Many Requests. It is used when a rate limiter has triggered. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + parameters: + Path.apfId: + name: apfId + in: path + description: "Identifier of the entity that registers the service API. If the\ + \ MEC app plays the role of the APF, this variable shall be set to the value\ + \ of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays\ + \ the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + Path.subscriberId: + name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + Path.SubscriptionId: + name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + Path.serviceApiId: + name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + Query.vend-spec-etsi-mec-sercategory-id: + name: vend-spec-etsi-mec-sercategory-id + in: query + description: Vendor-specific query parameter for service category ID. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id\"\ + , \"value\": \"serviceCategoryId\"}" + Query.vend-spec-etsi-mec-serinstance-id: + name: vend-spec-etsi-mec-serinstance-id + in: query + description: Vendor-specific query parameter for service instance ID. The "target" + attribute shall be set to "/apiId". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/apiId\", \"value\": \"serviceInstanceId\"}" + Query.api-name: + name: api-name + in: query + description: "This query parameter corresponds to the parameter \"ser_name\"\ + \ as defined in clause 8.2.3.3.1. As opposed to the cardinality of ser_instance_id\ + \ defined in clause 8.2.3.3.1 that is 0..N, this parameter only supports a\ + \ cardinality of 0..1." + required: false + style: form + explode: true + schema: + type: array + items: + type: string + Query.api-invoker-id: + name: api-invoker-id + in: query + description: "If the Discover_Service_API is produced by the MEC platform towards\ + \ the MEC applications, this identifier shall be set to the value of the \"\ + appInstanceId\" (see clause 7.1.2.6). If the Discover_Service_API is produced\ + \ by the CCF, the provisions in clause 8.1.2.2.3.1 of 3GPP TS 29.222 [21]\ + \ apply. " + required: false + style: form + explode: true + schema: + type: string + Query.vend-spec-etsi-mec-scope-of-locality: + name: vend-spec-etsi-mec-scope-of-locality + in: query + description: Vendor-specific query parameter for scope of locality. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality\"\ + , \"value\": \"scopeOfLocalityValue\"}" + Query.vend-spec-etsi-mec-is-local: + name: vend-spec-etsi-mec-is-local + in: query + description: Vendor-specific query parameter for is local. The "target" attribute + shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal\"\ + , \"value\": \"true\"}" + Query.vend-spec-etsi-mec-consumed-local-only: + name: vend-spec-etsi-mec-consumed-local-only + in: query + description: Vendor-specific query parameter for consumed local only. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly\"\ + , \"value\": \"true\"}" + requestBodies: + EventNotification: + content: + application/json: + schema: + $ref: '#/components/schemas/EventNotification' + required: true diff --git a/go-apps/meep-app-enablement/server/app-enablement.go b/go-apps/meep-app-enablement/server/app-enablement.go index cb3c9dc3f..2c03feddc 100644 --- a/go-apps/meep-app-enablement/server/app-enablement.go +++ b/go-apps/meep-app-enablement/server/app-enablement.go @@ -24,6 +24,7 @@ import ( "sync" as "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-app-enablement/server/app-support" + cm "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-app-enablement/server/capif-mgmt" sm "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-app-enablement/server/service-mgmt" httpLog "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-http-logger" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" @@ -125,6 +126,12 @@ func Init() (err error) { } log.Info("Service Management created") + // Initialize Capif Management + err = cm.Init(sandboxName, mepName, hostUrl, mqLocal, redisAddr, &mutex) + if err != nil { + return err + } + log.Info("Service Management created") // Initialize App Support err = as.Init(sandboxName, mepName, hostUrl, mqLocal, redisAddr, &mutex) if err != nil { @@ -144,6 +151,11 @@ func Run() (err error) { return err } + err = cm.Run() + if err != nil { + return err + } + err = as.Run() if err != nil { return err @@ -189,6 +201,7 @@ func Stop() { } _ = sm.Stop() + _ = cm.Stop() _ = as.Stop() // Remove APIs diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/README.md b/go-apps/meep-app-enablement/server/capif-mgmt/README.md new file mode 100644 index 000000000..37ee53989 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/README.md @@ -0,0 +1,25 @@ +# Go API Server for server + +MEC Service Management Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC011 Application Enablement API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/02.02.01_60/gs_MEC011v020201p.pdf)

[Copyright (c) ETSI 2024](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-app-enablement](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-app-enablement/server/service-mgmt)

**Type & Usage**
Edge Service used by edge applications that want to get information about services in the network

**Note**
AdvantEDGE supports all of Service Management API endpoints (see below). + +## Overview +This server was generated by the [swagger-codegen] +(https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. +- + +To see how to make this your own, look here: + +[README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md) + +- API version: 3.1.1 +- Build date: 2024-03-25T08:32:22.065107-05:00 + + +### Running the server +To run the server, follow these simple steps: + +``` +go run main.go +``` + diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go new file mode 100644 index 000000000..e230ebd1a --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 The AdvantEDGE Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * AdvantEDGE Service Management API + * + * MEC Service Management Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC011 Application Enablement API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/03.01.01_60/gs_MEC011v030101p.pdf)

[Copyright (c) ETSI 2024](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-app-enablement](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-app-enablement/server/service-mgmt)

**Type & Usage**
Edge Service used by edge applications that want to get information about services in the network

**Note**
AdvantEDGE supports all of Service Management API endpoints (see below). + * + * API version: 3.1.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +import ( + "net/http" +) + +func AppServicesGET(w http.ResponseWriter, r *http.Request) { + appServicesGET(w, r) +} + +func AppServicesPOST(w http.ResponseWriter, r *http.Request) { + appServicesPOST(w, r) +} + +func AppServicesServiceIdDELETE(w http.ResponseWriter, r *http.Request) { + appServicesByIdDELETE(w, r) +} + +func AppServicesServiceIdGET(w http.ResponseWriter, r *http.Request) { + appServicesByIdGET(w, r) +} + +func AppServicesServiceIdPUT(w http.ResponseWriter, r *http.Request) { + appServicesByIdPUT(w, r) +} + +func ApplicationsSubscriptionDELETE(w http.ResponseWriter, r *http.Request) { + applicationsSubscriptionDELETE(w, r) +} + +func ApplicationsSubscriptionGET(w http.ResponseWriter, r *http.Request) { + applicationsSubscriptionGET(w, r) +} + +func ApplicationsSubscriptionsGET(w http.ResponseWriter, r *http.Request) { + applicationsSubscriptionsGET(w, r) +} + +func ApplicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { + applicationsSubscriptionsPOST(w, r) +} + +func ServicesGET(w http.ResponseWriter, r *http.Request) { + servicesGET(w, r) +} + +func ServicesServiceIdGET(w http.ResponseWriter, r *http.Request) { + servicesByIdGET(w, r) +} + +func GetIndividualMECService(w http.ResponseWriter, r *http.Request) { + getIndividualMECService(w, r) +} + +func PatchIndividualMECService(w http.ResponseWriter, r *http.Request) { + patchIndividualMECService(w, r) +} + +func TransportsGET(w http.ResponseWriter, r *http.Request) { + transportsGET(w, r) +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go new file mode 100644 index 000000000..156f4b202 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 The AdvantEDGE Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package server + +import ( + "encoding/json" + + log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" +) + +func convertServiceInfoToJson(obj *ServiceInfo) 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) + if err != nil { + log.Error(err.Error()) + return nil + } + return &obj +} + +func convertSerAvailabilityNotifSubToJson(obj *SerAvailabilityNotificationSubscription) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + +func convertJsonToSerAvailabilityNotifSub(jsonData string) *SerAvailabilityNotificationSubscription { + var obj SerAvailabilityNotificationSubscription + err := json.Unmarshal([]byte(jsonData), &obj) + if err != nil { + log.Error(err.Error()) + return nil + } + return &obj +} + +func convertServiceAvailabilityNotifToJson(obj *ServiceAvailabilityNotification) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + +func convertProblemDetailsToJson(obj *ProblemDetails) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + +func convertSubscriptionLinkListToJson(obj *SubscriptionLinkList) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + +func convertServiceLivenessInfoToJson(obj *ServiceLivenessInfo) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + +// func convertMecServiceMgmtApiSubscriptionLinkListToJson(obj *MecServiceMgmtApiSubscriptionLinkList) string { +// jsonInfo, err := json.Marshal(*obj) +// if err != nil { +// log.Error(err.Error()) +// return "" +// } +// return string(jsonInfo) +// } + +func convertProblemDetailstoJson(probdetails *ProblemDetails) string { + jsonInfo, err := json.Marshal(*probdetails) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_app_instance_id_services_body.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_app_instance_id_services_body.go new file mode 100644 index 000000000..64cacc1b8 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_app_instance_id_services_body.go @@ -0,0 +1,14 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// New ServiceInfo with updated \"state\" is included as entity body of the request +type AppInstanceIdServicesBody struct { +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_category_ref.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_category_ref.go new file mode 100644 index 000000000..57ed174b7 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_category_ref.go @@ -0,0 +1,22 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents the category reference +type CategoryRef struct { + // Reference of the catalogue + Href string `json:"href"` + // Unique identifier of the category + Id string `json:"id"` + // Name of the category, example values include RNI, Location & Bandwidth Management + Name string `json:"name"` + // Category version + Version string `json:"version"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_address.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_address.go new file mode 100644 index 000000000..39c1377b4 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_address.go @@ -0,0 +1,18 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// A IP address and port pair +type EndPointInfoAddress struct { + // Host portion of the address + Host string `json:"host"` + // Port portion of the address + Port int32 `json:"port"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_addresses.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_addresses.go new file mode 100644 index 000000000..2301ae879 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_addresses.go @@ -0,0 +1,16 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents information about a transport endpoint. +type EndPointInfoAddresses struct { + // Entry point information of the service as one or more pairs of IP address and port. See note. + Addresses []EndPointInfoAddress `json:"addresses"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_alternative.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_alternative.go new file mode 100644 index 000000000..6caeab83a --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_alternative.go @@ -0,0 +1,16 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents information about a transport endpoint. +type EndPointInfoAlternative struct { + // Entry point information of the service in a format defined by an implementation, or in an external specification. See note. + Alternative *interface{} `json:"alternative"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_fqdn.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_fqdn.go new file mode 100644 index 000000000..37a0b8570 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_fqdn.go @@ -0,0 +1,16 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents information about a transport endpoint. +type EndPointInfoFqdn struct { + // Fully Qualified Domain Name of the service. See note. + Fqdn []string `json:"fqdn"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_uris.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_uris.go new file mode 100644 index 000000000..e6e1c67a0 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_end_point_info_uris.go @@ -0,0 +1,16 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents information about a transport endpoint. +type EndPointInfoUris struct { + // Entry point information of the service as string, formatted according to URI syntax + Uris []string `json:"uris"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_link_type.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_link_type.go new file mode 100644 index 000000000..595753dac --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_link_type.go @@ -0,0 +1,16 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents a type of link and may be referenced from data structures +type LinkType struct { + // URI referring to a resource + Href string `json:"href,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_locality_type.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_locality_type.go new file mode 100644 index 000000000..268422127 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_locality_type.go @@ -0,0 +1,24 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// LocalityType : The scope of locality as expressed by \"consumedLocalOnly\" and \"isLocal\". If absent, defaults to MEC_HOST +type LocalityType string + +// List of LocalityType +const ( + // FSCOM Change manually + MEC_SYSTEM_LocalityType LocalityType = "MEC_SYSTEM" + MEC_HOST_LocalityType LocalityType = "MEC_HOST" + NFVI_POP_LocalityType LocalityType = "NFVI_POP" + ZONE_LocalityType LocalityType = "ZONE" + ZONE_GROUP_LocalityType LocalityType = "ZONE_GROUP" + NFVI_NODE_LocalityType LocalityType = "NFVI_NODE" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext.go new file mode 100644 index 000000000..e98afb5cb --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext.go @@ -0,0 +1,24 @@ +/* + * 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 MecServiceInfoCapifExt 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"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list.go new file mode 100644 index 000000000..95bd180c5 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list.go @@ -0,0 +1,15 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents a list of links related to currently existing subscriptions for a MEC application instance. This information is returned when sending a request to receive current subscriptions. +type MecServiceMgmtApiSubscriptionLinkList struct { + Links *MecServiceMgmtApiSubscriptionLinkListLinks `json:"_links"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_links.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_links.go new file mode 100644 index 000000000..0cbedcb21 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_links.go @@ -0,0 +1,17 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// Self-referring URI. +type MecServiceMgmtApiSubscriptionLinkListLinks struct { + Self *LinkType `json:"self"` + // The MEC application instance's subscriptions + Subscriptions []MecServiceMgmtApiSubscriptionLinkListSubscription `json:"subscriptions,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_subscription.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_subscription.go new file mode 100644 index 000000000..194c7ab14 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_mgmt_api_subscription_link_list_subscription.go @@ -0,0 +1,18 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// A link to a subscription. +type MecServiceMgmtApiSubscriptionLinkListSubscription struct { + // URI referring to a resource + Href string `json:"href"` + // The value shall be se to SerAvailabilityNotificationSubscription. + Rel string `json:"rel"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_one_of_transport_info_endpoint.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_one_of_transport_info_endpoint.go new file mode 100644 index 000000000..bae848c47 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_one_of_transport_info_endpoint.go @@ -0,0 +1,17 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type OneOfTransportInfoEndpoint struct { + EndPointInfoUris + EndPointInfoFqdn + EndPointInfoAddresses + EndPointInfoAlternative +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_one_ofapp_instance_id_services_body.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_one_ofapp_instance_id_services_body.go new file mode 100644 index 000000000..b1429a050 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_one_ofapp_instance_id_services_body.go @@ -0,0 +1,13 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type OneOfappInstanceIdServicesBody struct { +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_problem_details.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_problem_details.go new file mode 100644 index 000000000..a57f2a1c1 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_problem_details.go @@ -0,0 +1,23 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type ProblemDetails struct { + // A URI reference according to IETF RFC 3986 that identifies the problem type + Type_ string `json:"type,omitempty"` + // A short, human-readable summary of the problem type + Title string `json:"title,omitempty"` + // The HTTP status code for this occurrence of the problem + Status int32 `json:"status,omitempty"` + // A human-readable explanation specific to this occurrence of the problem + Detail string `json:"detail,omitempty"` + // A URI reference that identifies the specific occurrence of the problem + Instance string `json:"instance,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info.go new file mode 100644 index 000000000..0a9d5ae62 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info.go @@ -0,0 +1,15 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents security information related to a transport +type SecurityInfo struct { + OAuth2Info *SecurityInfoOAuth2Info `json:"oAuth2Info,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info.go new file mode 100644 index 000000000..825b34131 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info.go @@ -0,0 +1,18 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// Parameters related to use of OAuth 2.0 +type SecurityInfoOAuth2Info struct { + // List of supported OAuth 2.0 grant types. + GrantTypes []SecurityInfoOAuth2InfoGrantType `json:"grantTypes"` + // The token endpoint + TokenEndpoint string `json:"tokenEndpoint"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info_grant_type.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info_grant_type.go new file mode 100644 index 000000000..c527aadae --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_security_info_o_auth2_info_grant_type.go @@ -0,0 +1,21 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// SecurityInfoOAuth2InfoGrantType : OAuth 2.0 grant type +type SecurityInfoOAuth2InfoGrantType string // FSCOM CHanged manually + +// List of SecurityInfo.OAuth2Info.GrantType +const ( + AUTHORIZATION_CODE SecurityInfoOAuth2InfoGrantType = "OAUTH2_AUTHORIZATION_CODE" + IMPLICIT_GRANT SecurityInfoOAuth2InfoGrantType = "OAUTH2_IMPLICIT_GRANT" + RESOURCE_OWNER SecurityInfoOAuth2InfoGrantType = "OAUTH2_RESOURCE_OWNER" + CLIENT_CREDENTIALS SecurityInfoOAuth2InfoGrantType = "OAUTH2_CLIENT_CREDENTIALS" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_self.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_self.go new file mode 100644 index 000000000..93520de48 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_self.go @@ -0,0 +1,15 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// Self-referring URI. +type Self struct { + Self *LinkType `json:"self"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription.go new file mode 100644 index 000000000..dbb5671d3 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription.go @@ -0,0 +1,21 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type SerAvailabilityNotificationSubscription struct { + // Shall be set to SerAvailabilityNotificationSubscription. + SubscriptionType string `json:"subscriptionType"` + // URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response. + CallbackReference string `json:"callbackReference"` + + Links *Self `json:"_links"` + + FilteringCriteria *SerAvailabilityNotificationSubscriptionFilteringCriteria `json:"filteringCriteria,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription_filtering_criteria.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription_filtering_criteria.go new file mode 100644 index 000000000..7a84db97e --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_ser_availability_notification_subscription_filtering_criteria.go @@ -0,0 +1,24 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// Filtering criteria to match services for which events are requested to be reported. If absent, matches all services. All child attributes are combined with the logical \"AND\" operation. +type SerAvailabilityNotificationSubscriptionFilteringCriteria struct { + // Identifiers of service instances about which to report events. + SerInstanceIds []string `json:"serInstanceIds,omitempty"` + // Names of services about which to report events. + SerNames []string `json:"serNames,omitempty"` + // Categories of services about which to report events. + SerCategories []CategoryRef `json:"serCategories,omitempty"` + // States of the services about which to report events. If the event is a state change, this filter represents the state after the change. + States []ServiceState `json:"states,omitempty"` + // Indicate whether the service is located in the same locality (as defined by scopeOfLocality) as the consuming MEC application. + IsLocal bool `json:"isLocal,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_serializer_type.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_serializer_type.go new file mode 100644 index 000000000..a3fa9f14a --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_serializer_type.go @@ -0,0 +1,20 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// SerializerType : The enumeration represents types of serializers +type SerializerType string + +// List of SerializerType +const ( + JSON SerializerType = "JSON" + XML SerializerType = "XML" + PROTOBUF3 SerializerType = "PROTOBUF3" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go new file mode 100644 index 000000000..6ad3723ef --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go @@ -0,0 +1,19 @@ +/* + * 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 ServiceApiDescription struct { + // Shall be set to the value of the \"serName\" attribute as defined in clause 8.1.2.2. + ApiName string `json:"apiName,omitempty"` + // If present, shall be set to the value of the \"serInstanceId\" attribute as defined in clause 8.1.2.2. + ApiId string `json:"apiId,omitempty"` + + VendorSpecificUrnetsimeccapifextserviceInfo *MecServiceInfoCapifExt `json:"vendorSpecific-urn:etsi:mec:capifext:service-info,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification.go new file mode 100644 index 000000000..c6a578713 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification.go @@ -0,0 +1,20 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents the service availability information. +type ServiceAvailabilityNotification struct { + // Shall be set to SerAvailabilityNotificationSubscription. + NotificationType string `json:"notificationType"` + + ServiceReferences []ServiceAvailabilityNotificationServiceReferences `json:"serviceReferences"` + + Links *Subscription `json:"_links"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_change_type.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_change_type.go new file mode 100644 index 000000000..d171b221b --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_change_type.go @@ -0,0 +1,22 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// ServiceAvailabilityNotificationChangeType : Type of the change. Valid values: 1. ADDED: The service was newly added. 2. REMOVED: The service was removed. 3. STATE_CHANGED: Only the state of the service was changed. 4. ATTRIBUTES_CHANGED: At least one attribute of the service other than state was changed. The change may or may not include changing the state. +type ServiceAvailabilityNotificationChangeType string // FSCOM Changed manually + +// List of ServiceAvailabilityNotification.ChangeType +const ( + // FSCOM Changed manually + ADDED_ServiceAvailabilityNotificationChangeType ServiceAvailabilityNotificationChangeType = "ADDED" + REMOVED_ServiceAvailabilityNotificationChangeType ServiceAvailabilityNotificationChangeType = "REMOVED" + STATE_CHANGED_ServiceAvailabilityNotificationChangeType ServiceAvailabilityNotificationChangeType = "STATE_CHANGED" + ATTRIBUTES_CHANGED_ServiceAvailabilityNotificationChangeType ServiceAvailabilityNotificationChangeType = "ATTRIBUTES_CHANGED" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go new file mode 100644 index 000000000..9315e529d --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go @@ -0,0 +1,23 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// List of links to services whose availability has changed. +type ServiceAvailabilityNotificationServiceReferences struct { + Link *LinkType `json:"link,omitempty"` + // The name of the service. This is how the service producing MEC application identifies the service instance it produces. + SerName string `json:"serName"` + // Identifier of the service instance assigned by the MEC platform. + SerInstanceId string `json:"serInstanceId"` + + State *ServiceState `json:"state"` + + ChangeType *ServiceAvailabilityNotificationChangeType `json:"changeType"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_info.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_info.go new file mode 100644 index 000000000..874086373 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_info.go @@ -0,0 +1,40 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents the general information of a MEC service. +type ServiceInfo struct { + // Identifier of the service instance assigned by the MEC platform. + SerInstanceId string `json:"serInstanceId,omitempty"` + // The name of the service. This is how the service producing MEC application identifies the service instance it produces. + SerName string `json:"serName"` + + SerCategory *CategoryRef `json:"serCategory,omitempty"` + // Service version + Version string `json:"version"` + + State *ServiceState `json:"state"` + // Identifier of the platform-provided transport to be used by the service. Valid identifiers may be obtained using the \"Transport information query\" procedure. May be present in POST requests to signal the use of a platform-provided transport for the service, and shall be absent otherwise. See note 2. + TransportId string `json:"transportId,omitempty"` + + TransportInfo *TransportInfo `json:"transportInfo"` + + Serializer *SerializerType `json:"serializer"` + + ScopeOfLocality *LocalityType `json:"scopeOfLocality,omitempty"` + // Indicate whether the service can only be consumed by the MEC applications located in the same locality (as defined by scopeOfLocality) as this service instance. + ConsumedLocalOnly bool `json:"consumedLocalOnly,omitempty"` + // Indicate whether the service is located in the same locality (as defined by scopeOfLocality) as the consuming MEC application. + IsLocal bool `json:"isLocal,omitempty"` + // Interval (in seconds) between two consecutive \"heartbeat\" messages (see clause 8.2.10.3.3). If the service-producing application supports sending \"heartbeat\" messages, it shall include this attribute in the registration request. In this case, the application shall either set the value of this attribute to zero or shall use this attribute to propose a non-zero positive value for the liveness interval. If the application has provided this attribute in the request and the MEC platform requires \"heartbeat\" messages, the MEC platform shall return this attribute value in the HTTP responses. The MEC platform may use the value proposed in the request or may choose a different value. If the MEC platform does not require \"heartbeat\" messages for this service instance it shall omit the attribute in responses. + LivenessInterval int32 `json:"livenessInterval,omitempty"` + + Links *ServiceInfoLinks `json:"_links,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_info__links.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_info__links.go new file mode 100644 index 000000000..96e4a805d --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_info__links.go @@ -0,0 +1,16 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type ServiceInfoLinks struct { + Self *LinkType `json:"self"` + + Liveness *LinkType `json:"liveness,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info.go new file mode 100644 index 000000000..d85c56561 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info.go @@ -0,0 +1,18 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type ServiceLivenessInfo struct { + State *ServiceState `json:"state"` + + TimeStamp *ServiceLivenessInfoTimeStamp `json:"timeStamp"` + // The interval (in seconds) between two consecutive \"heartbeat\" messages (see clause 8.2.10.3.3) that MEC platform has determined. + Interval int32 `json:"interval"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info_time_stamp.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info_time_stamp.go new file mode 100644 index 000000000..26ce9014f --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_info_time_stamp.go @@ -0,0 +1,17 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// The time when the last \"heartbeat\" message was received by MEC platform +type ServiceLivenessInfoTimeStamp struct { + Seconds int32 `json:"seconds"` + + NanoSeconds int32 `json:"nanoSeconds"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_update.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_update.go new file mode 100644 index 000000000..c3a65e663 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_liveness_update.go @@ -0,0 +1,14 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +type ServiceLivenessUpdate struct { + State *ServiceState `json:"state"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_state.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_state.go new file mode 100644 index 000000000..1ebb73e85 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_state.go @@ -0,0 +1,20 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// ServiceState : This enumeration defines the possible states of a service. +type ServiceState string + +// List of ServiceState +var ( // FSCOM Change manually + ACTIVE_ServiceState ServiceState = "ACTIVE" + INACTIVE_ServiceState ServiceState = "INACTIVE" + SUSPENDED_ServiceState ServiceState = "SUSPENDED" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription.go new file mode 100644 index 000000000..ea0bf9e6d --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription.go @@ -0,0 +1,15 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// A link to the related subscription +type Subscription struct { + Subscription *LinkType `json:"subscription"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list.go new file mode 100644 index 000000000..180a44e98 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * AdvantEDGE Service Management API + * + * MEC Service Management Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC011 Application Enablement API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/02.02.01_60/gs_MEC011v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-app-enablement](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-app-enablement/server/service-mgmt)

**Type & Usage**
Edge Service used by edge applications that want to get information about services in the network

**Note**
AdvantEDGE supports all of Service Management API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents a list of links related to currently existing subscriptions for a MEC application instance. This information is returned when sending a request to receive current subscriptions. +type SubscriptionLinkList struct { + Links *SubscriptionLinkListLinks `json:"_links"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links.go new file mode 100644 index 000000000..addff4132 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * AdvantEDGE Service Management API + * + * MEC Service Management Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC011 Application Enablement API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/02.02.01_60/gs_MEC011v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-app-enablement](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-app-enablement/server/service-mgmt)

**Type & Usage**
Edge Service used by edge applications that want to get information about services in the network

**Note**
AdvantEDGE supports all of Service Management API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// Self-referring URI. +type SubscriptionLinkListLinks struct { + Self *LinkType `json:"self"` + // The MEC application instance's subscriptions + Subscriptions []SubscriptionLinkListLinksSubscriptions `json:"subscriptions,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links_subscriptions.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links_subscriptions.go new file mode 100644 index 000000000..45001d0b1 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_subscription_link_list__links_subscriptions.go @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 The AdvantEDGE Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * AdvantEDGE Service Management API + * + * MEC Service Management Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC011 Application Enablement API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/02.02.01_60/gs_MEC011v020201p.pdf)

[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt)

**Micro-service**
[meep-app-enablement](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-app-enablement/server/service-mgmt)

**Type & Usage**
Edge Service used by edge applications that want to get information about services in the network

**Note**
AdvantEDGE supports all of Service Management API endpoints (see below). + * + * API version: 2.2.1 + * Contact: AdvantEDGE@InterDigital.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// A link to a subscription. +type SubscriptionLinkListLinksSubscriptions struct { + // URI referring to a resource + Href string `json:"href"` + // Type of the subscription. The values are as defined in the \"subscriptionType\" attribute for each different Mp1 event subscription data type. + SubscriptionType string `json:"subscriptionType"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_transport_info.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_transport_info.go new file mode 100644 index 000000000..2e18708ef --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_transport_info.go @@ -0,0 +1,32 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// This type represents the general information of a MEC service. +type TransportInfo struct { + // The identifier of this transport + Id string `json:"id"` + // The name of this transport + Name string `json:"name"` + // Human-readable description of this transport + Description string `json:"description,omitempty"` + + Type_ *TransportType `json:"type"` + // The name of the protocol used. Shall be set to HTTP for a REST API. + Protocol string `json:"protocol"` + // The version of the protocol used + Version string `json:"version"` + // This type represents information about a transport endpoint + Endpoint *OneOfTransportInfoEndpoint `json:"endpoint"` + + Security *SecurityInfo `json:"security"` + // Additional implementation specific details of the transport + ImplSpecificInfo string `json:"implSpecificInfo,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_transport_type.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_transport_type.go new file mode 100644 index 000000000..ebb54a5bb --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_transport_type.go @@ -0,0 +1,25 @@ +/* + * MEC Service Management API + * + * The ETSI MEC ISG MEC011 MEC Service Management API described using OpenAPI + * + * API version: 3.1.1 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package server + +// TransportType : The enumeration TransportType represents types of transports +type TransportType string + +// List of TransportType +const ( + // FSCOM Change manually + REST_HTTP_TransportType TransportType = "REST_HTTP" + MB_TOPIC_BASED_TransportType TransportType = "MB_TOPIC_BASED" + MB_ROUTING_TransportType TransportType = "MB_ROUTING" + MB_PUBSUB_TransportType TransportType = "MB_PUBSUB" + RPC_TransportType TransportType = "RPC" + RPC_STREAMING_TransportType TransportType = "RPC_STREAMING" + WEBSOCKET_TransportType TransportType = "WEBSOCKET" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go new file mode 100644 index 000000000..e307f92b5 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -0,0 +1,1796 @@ +/* + * Copyright (c) 2024 The AdvantEDGE Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package server + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "strconv" + "strings" + "sync" + "time" + + dkm "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-key-mgr" + log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" + mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq" + redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis" + subs "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-subscriptions" + uuid "github.com/google/uuid" + + "github.com/gorilla/mux" +) + +const moduleName = "meep-app-enablement" +const svcMgmtBasePath = "mec_service_mgmt/v1/" +const appEnablementKey = "app-enablement" +const globalMepName = "global" +const SER_AVAILABILITY_NOTIF_SUB_TYPE = "SerAvailabilityNotificationSubscription" +const SER_AVAILABILITY_NOTIF_TYPE = "SerAvailabilityNotification" +const APP_STATE_READY = "READY" + +// const logModuleAppEnablement = "meep-app-enablement" +const serviceName = "App Enablement Service" + +// App Info fields +const fieldState = "state" + +// MQ payload fields +const fieldSvcInfo = "svc-info" +const fieldAppId = "app-id" +const fieldChangeType = "change-type" +const fieldMepName = "mep-name" + +var mutex *sync.Mutex +var redisAddr string // = "meep-redis-master.default.svc.cluster.local:6379" +var APP_ENABLEMENT_DB = 0 +var rc *redis.Connector +var mqLocal *mq.MsgQueue +var hostUrl *url.URL +var sandboxName string +var mepName string +var basePath string +var baseKey string +var baseKeyAnyMep string +var subMgr *subs.SubscriptionMgr + +type ServiceInfoList struct { + Services []ServiceInfo + ConsumedLocalOnlyPresent bool + IsLocalPresent bool + Filters *FilterParameters +} + +type FilterParameters struct { + serInstanceId []string + serName []string + serCategoryId string + consumedLocalOnly bool + isLocal bool + scopeOfLocality string +} + +type StateData struct { + State ServiceState + AppId string +} + +var livenessTimerList map[string]ServiceLivenessInfo + +func Init(sandbox string, mep string, host *url.URL, msgQueue *mq.MsgQueue, redisAddr_ string, globalMutex *sync.Mutex) (err error) { + redisAddr = redisAddr_ + sandboxName = sandbox + mepName = mep + hostUrl = host + mqLocal = msgQueue + mutex = globalMutex + + // Set base path & storage key + if mepName == globalMepName { + basePath = "/" + sandboxName + "/" + svcMgmtBasePath + baseKey = dkm.GetKeyRoot(sandboxName) + appEnablementKey + ":mep-global:" + baseKeyAnyMep = dkm.GetKeyRoot(sandboxName) + appEnablementKey + ":mep-global:" + } else { + basePath = "/" + sandboxName + "/" + mepName + "/" + svcMgmtBasePath + baseKey = dkm.GetKeyRoot(sandboxName) + appEnablementKey + ":mep:" + mepName + ":" + baseKeyAnyMep = dkm.GetKeyRoot(sandboxName) + appEnablementKey + ":mep:*:" + } + + // Connect to Redis DB + rc, err = redis.NewConnector(redisAddr, APP_ENABLEMENT_DB) + if err != nil { + log.Error("Failed connection to Redis DB. Error: ", err) + return err + } + log.Info("Connected to Redis DB") + + // Create Subscription Manager + subMgrCfg := &subs.SubscriptionMgrCfg{ + Module: moduleName, + Sandbox: sandboxName, + Mep: mepName, + Service: serviceName, + Basekey: baseKey, + MetricsEnabled: true, + ExpiredSubCb: nil, + PeriodicSubCb: nil, + TestNotifCb: nil, + NewWsCb: nil, + } + subMgr, err = subs.NewSubscriptionMgr(subMgrCfg, redisAddr) + if err != nil { + log.Error("Failed to create Subscription Manager. Error: ", err) + return err + } + log.Info("Created Subscription Manager") + + livenessTimerList = make(map[string]ServiceLivenessInfo) + + // TODO -- Initialize subscriptions from DB + + return nil +} + +// Run - Start Service Mgmt +func Run() (err error) { + + // Register Message Queue handler + handler := mq.MsgHandler{Handler: msgHandler, UserData: nil} + _, err = mqLocal.RegisterHandler(handler) + if err != nil { + log.Error("Failed to listen for sandbox updates: ", err.Error()) + return err + } + + return nil +} + +// Stop - Stop Service Mgmt +func Stop() (err error) { + + if len(livenessTimerList) != 0 { + livenessTimerList = make(map[string]ServiceLivenessInfo) + } + + return nil +} + +func createLivenessTicker(sInfo ServiceInfo) { + log.Debug(">>> createLivenessTicker: ", sInfo) + + livenessTimerList[sInfo.SerInstanceId] = ServiceLivenessInfo{ + State: &ACTIVE_ServiceState, + TimeStamp: &ServiceLivenessInfoTimeStamp{Seconds: 0, NanoSeconds: 0}, + Interval: sInfo.LivenessInterval, + } +} + +func updateLivenessTicker(sInfo ServiceInfo) { + log.Debug(">>> updateLivenessTicker: ", sInfo) + + if sInfo.LivenessInterval != livenessTimerList[sInfo.SerInstanceId].Interval { + deleteLivenessTicker(sInfo.SerInstanceId) + createLivenessTicker(sInfo) + } +} + +func deleteLivenessTicker(serInstanceId string) { + log.Debug(">>> deleteLivenessTicker: ", serInstanceId) + + delete(livenessTimerList, serInstanceId) +} + +// Message Queue handler +func msgHandler(msg *mq.Msg, userData interface{}) { + switch msg.Message { + case mq.MsgMecSvcUpdate: + log.Debug("RX MSG: ", mq.PrintMsg(msg)) + sInfoJson := msg.Payload[fieldSvcInfo] + mep := msg.Payload[fieldMepName] + changeType := msg.Payload[fieldChangeType] + processSvcUpdate(sInfoJson, mep, changeType) + default: + } +} + +func appServicesPOST(w http.ResponseWriter, r *http.Request) { + log.Info("appServicesPOST") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + appId := vars["appInstanceId"] + + 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 + } + + // 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 + sInfoPost := ServiceInfo{ + ScopeOfLocality: &locality, + IsLocal: true, + ConsumedLocalOnly: true, + } + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&sInfoPost) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + + // Check for mandatory properties + if sInfoPost.SerInstanceId != "" { + errStr := "Service instance ID must not be present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.SerName == "" { + errStr := "Mandatory Service Name parameter not present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.Version == "" { + errStr := "Mandatory Service Version parameter not present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.State == nil { + errStr := "Mandatory Service State parameter not present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.Serializer == nil { + errStr := "Mandatory Serializer parameter not present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.SerCategory != nil { + errStr := validateCategoryRef(sInfoPost.SerCategory) + if errStr != "" { + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + } + if (sInfoPost.TransportId != "" && sInfoPost.TransportInfo != nil) || + (sInfoPost.TransportId == "" && sInfoPost.TransportInfo == nil) { + errStr := "Either transportId or transportInfo but not both shall be present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.Links != nil { + errStr := "Links parameter should not be present in request" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + if sInfoPost.TransportInfo != nil { + if sInfoPost.TransportInfo.Id == "" || + sInfoPost.TransportInfo.Name == "" || + string(*sInfoPost.TransportInfo.Type_) == "" || + sInfoPost.TransportInfo.Protocol == "" || + sInfoPost.TransportInfo.Version == "" || + sInfoPost.TransportInfo.Endpoint == nil { + errStr := "Id, Name, Type, Protocol, Version, Endpoint are all mandatory parameters of TransportInfo" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + } + + // Create Service + sInfo := &ServiceInfo{ + SerInstanceId: uuid.New().String(), + SerName: sInfoPost.SerName, + SerCategory: sInfoPost.SerCategory, + Version: sInfoPost.Version, + State: sInfoPost.State, + TransportInfo: sInfoPost.TransportInfo, + Serializer: sInfoPost.Serializer, + ScopeOfLocality: sInfoPost.ScopeOfLocality, + ConsumedLocalOnly: sInfoPost.ConsumedLocalOnly, + // although IsLocal is reevaluated when a query is replied to, value stored in sInfo as is for now + IsLocal: sInfoPost.IsLocal, + LivenessInterval: sInfoPost.LivenessInterval, + } + sInfo.Links = &ServiceInfoLinks{ + Self: &LinkType{ + Href: hostUrl.String() + basePath + "applications/" + appId + "/services/" + sInfo.SerInstanceId, + }, + } + if sInfo.LivenessInterval != 0 { + sInfo.Links.Liveness = &LinkType{ + Href: hostUrl.String() + basePath + "resource_uri_allocated_by_MEC_platform/" + sInfo.SerInstanceId, + } + } + + err, retCode := setService(appId, sInfo, ADDED_ServiceAvailabilityNotificationChangeType) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), retCode) + return + } + + // Send response + w.Header().Set("Location", hostUrl.String()+basePath+"applications/"+appId+"/services/"+sInfo.SerInstanceId) + w.WriteHeader(http.StatusCreated) + fmt.Fprint(w, convertServiceInfoToJson(sInfo)) +} + +func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + log.Info("appServicesByIdPUT") + vars := mux.Vars(r) + appId := vars["appInstanceId"] + svcId := vars["serviceId"] + + 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 := ServiceInfo{ + 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 + } + + // 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(&sInfo)) +} + +func appServicesByIdDELETE(w http.ResponseWriter, r *http.Request) { + log.Info("appServicesByIdDELETE") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + appId := vars["appInstanceId"] + svcId := vars["serviceId"] + + 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 service info + sInfoJson, err := getServiceById(appId, svcId) + if err != nil { + log.Error(err.Error()) + w.WriteHeader(http.StatusNotFound) + return + } + sInfo := convertJsonToServiceInfo(sInfoJson) + + // Delete service + err = delServiceById(appId, svcId) + if err != nil { + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + + // Notify remote listeners (except if global instance) + changeType := REMOVED_ServiceAvailabilityNotificationChangeType + if mepName != globalMepName { + sendSvcUpdateMsg(sInfoJson, appId, mepName, string(changeType)) + } + + // Send local service availability notifications + checkSerAvailNotification(sInfo, mepName, changeType) + + w.WriteHeader(http.StatusNoContent) +} + +func appServicesGET(w http.ResponseWriter, r *http.Request) { + log.Info("appServicesGET") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + appId := vars["appInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + // Get App instance + appInfo, err := getAppInfoAnyMep(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 + } + + getServices(w, r, appId) +} + +func appServicesByIdGET(w http.ResponseWriter, r *http.Request) { + log.Info("appServicesByIdGET") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + svcId := vars["serviceId"] + appId := vars["appInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + // Get App instance + appInfo, err := getAppInfoAnyMep(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 + } + + getService(w, r, appId, svcId) +} + +func servicesByIdGET(w http.ResponseWriter, r *http.Request) { + log.Info("servicesByIdGET") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + svcId := vars["serviceId"] + + mutex.Lock() + defer mutex.Unlock() + + getService(w, r, "", svcId) +} + +func servicesGET(w http.ResponseWriter, r *http.Request) { + log.Info("servicesGET") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + + mutex.Lock() + defer mutex.Unlock() + + getServices(w, r, "") +} + +func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { + log.Info("applicationsSubscriptionsPOST") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + appId := vars["appInstanceId"] + + 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 + } + + // Retrieve subscription request + if r.Body == nil { + err := errors.New("Request body is missing") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + var serAvailNotifSub SerAvailabilityNotificationSubscription + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&serAvailNotifSub) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + + // Validate mandatory properties + if serAvailNotifSub.CallbackReference == "" { + log.Error("Mandatory CallbackReference parameter not present") + errHandlerProblemDetails(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest) + return + } + if serAvailNotifSub.SubscriptionType != SER_AVAILABILITY_NOTIF_SUB_TYPE { + log.Error("SubscriptionType shall be SerAvailabilityNotificationSubscription") + errHandlerProblemDetails(w, "SubscriptionType shall be SerAvailabilityNotificationSubscription", http.StatusBadRequest) + return + } + + // Validate Service filter params + if serAvailNotifSub.FilteringCriteria != nil { + nbMutuallyExclusiveParams := 0 + if serAvailNotifSub.FilteringCriteria.SerInstanceIds != nil { + if len(serAvailNotifSub.FilteringCriteria.SerInstanceIds) > 0 { + nbMutuallyExclusiveParams++ + } + } + if serAvailNotifSub.FilteringCriteria.SerNames != nil { + if len(serAvailNotifSub.FilteringCriteria.SerNames) > 0 { + nbMutuallyExclusiveParams++ + } + } + if serAvailNotifSub.FilteringCriteria.SerCategories != nil { + for _, categoryRef := range serAvailNotifSub.FilteringCriteria.SerCategories { + errStr := validateCategoryRef(&categoryRef) + if errStr != "" { + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + } + + if len(serAvailNotifSub.FilteringCriteria.SerCategories) > 0 { + nbMutuallyExclusiveParams++ + } + } + if nbMutuallyExclusiveParams > 1 { + errStr := "FilteringCriteria attributes serInstanceIds, serNames, serCategories are mutually-exclusive" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + } + + // Get a new subscription ID + subId := subMgr.GenerateSubscriptionId() + + // Set resource link + serAvailNotifSub.Links = &Self{ + Self: &LinkType{ + Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId, + }, + } + + // Create & store subscription + subCfg := newSerAvailabilityNotifSubCfg(&serAvailNotifSub, subId, appId) + jsonSub := convertSerAvailabilityNotifSubToJson(&serAvailNotifSub) + _, err = subMgr.CreateSubscription(subCfg, jsonSub) + if err != nil { + log.Error("Failed to create subscription") + errHandlerProblemDetails(w, "Failed to create subscription", http.StatusInternalServerError) + return + } + + // Send response + w.Header().Set("Location", serAvailNotifSub.Links.Self.Href) + w.WriteHeader(http.StatusCreated) + fmt.Fprint(w, jsonSub) +} + +func applicationsSubscriptionGET(w http.ResponseWriter, r *http.Request) { + log.Info("applicationsSubscriptionGET") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + subId := vars["subscriptionId"] + appId := vars["appInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + // Get App instance info + 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 + } + + // Find subscription by ID + sub, err := subMgr.GetSubscription(subId) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + return + } + + // Validate subscription + // Validate subscription + if sub.Cfg.AppId != appId || sub.Cfg.Type != SER_AVAILABILITY_NOTIF_SUB_TYPE { + err = errors.New("Subscription not found") + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + return + } + + // Return original marshalled subscription + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, sub.JsonSubOrig) +} + +func applicationsSubscriptionDELETE(w http.ResponseWriter, r *http.Request) { + log.Info("applicationsSubscriptionDELETE") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + subId := vars["subscriptionId"] + appId := vars["appInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + // Get App instance info + 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 + } + + // Find subscription by ID + sub, err := subMgr.GetSubscription(subId) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + return + } + + // Validate subscription + if sub.Cfg.AppId != appId || sub.Cfg.Type != SER_AVAILABILITY_NOTIF_SUB_TYPE { + err = errors.New("Subscription not found") + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + return + } + + // Delete subscription + err = subMgr.DeleteSubscription(sub) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + + // Send response + w.WriteHeader(http.StatusNoContent) +} + +func applicationsSubscriptionsGET(w http.ResponseWriter, r *http.Request) { + log.Info("applicationsSubscriptionsGET") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + appId := vars["appInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + // Get App instance info + 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 subscriptions for App instance + subList, err := subMgr.GetFilteredSubscriptions(appId, SER_AVAILABILITY_NOTIF_SUB_TYPE) + if err != nil { + log.Error("Failed to get subscription list with err: ", err.Error()) + return + } + + // Create subscription link list + subscriptionLinkList := &SubscriptionLinkList{ + Links: &SubscriptionLinkListLinks{ + Self: &LinkType{ + Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions", + }, + }, + } + + for _, sub := range subList { + // Create subscription reference & append it to link list + subscription := SubscriptionLinkListLinksSubscriptions{ + // In v2.1.1 it should be SubscriptionType, but spec is expecting "rel" as per v1.1.1 + SubscriptionType: sub.Cfg.Type, + Href: sub.Cfg.Self, + } + subscriptionLinkList.Links.Subscriptions = append(subscriptionLinkList.Links.Subscriptions, subscription) + } + + // Send response + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, convertSubscriptionLinkListToJson(subscriptionLinkList)) +} + +func getIndividualMECService(w http.ResponseWriter, r *http.Request) { + log.Info("getIndividualMECService") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + + vars := mux.Vars(r) + serInstanceId := vars["serInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + if serInstanceId == "" { + err := errors.New("wrong request parameters") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + log.Info("getIndividualMECService: ", serInstanceId) + + if entry, ok := livenessTimerList[serInstanceId]; !ok { + err := errors.New("Invalid Service instance ID") + errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + return + } else { + entry.TimeStamp = &ServiceLivenessInfoTimeStamp{ + Seconds: int32(time.Now().Unix()), + } + fmt.Fprint(w, convertServiceLivenessInfoToJson(&entry)) + livenessTimerList[serInstanceId] = entry + } + + // Send response + w.WriteHeader(http.StatusOK) +} + +func patchIndividualMECService(w http.ResponseWriter, r *http.Request) { + log.Info("patchIndividualMECService") + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + + vars := mux.Vars(r) + serInstanceId := vars["serInstanceId"] + + mutex.Lock() + defer mutex.Unlock() + + if serInstanceId == "" { + err := errors.New("wrong request parameters") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + log.Info("patchIndividualMECService: ", serInstanceId) + + if entry, ok := livenessTimerList[serInstanceId]; !ok { + err := errors.New("Invalid Service instance ID") + errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + return + } else { + // Retrieve request + if r.Body == nil { + err := errors.New("Request body is missing") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + var serviceLivenessUpdate ServiceLivenessUpdate + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&serviceLivenessUpdate) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + log.Info("patchIndividualMECService: serviceLivenessUpdate: ", serviceLivenessUpdate) + if *serviceLivenessUpdate.State == ACTIVE_ServiceState { + entry.State = &ACTIVE_ServiceState + } else { // ETSI GS MEC 011 V3.2.1 (2024-04) Table 8.1.2.5-1: Attributes of ServiceLivenessUpdate + err := errors.New("Wrong body content") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + entry.TimeStamp = &ServiceLivenessInfoTimeStamp{ + Seconds: 0, + } + fmt.Fprint(w, convertServiceLivenessInfoToJson(&entry)) + livenessTimerList[serInstanceId] = entry + } + + // Send response + w.WriteHeader(http.StatusOK) +} + +func transportsGET(w http.ResponseWriter, r *http.Request) { + log.Info("transportsGET") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + + // Create transport info + var endpoint OneOfTransportInfoEndpoint + endpoint.Uris = append(endpoint.Uris, hostUrl.String()+basePath) + transportType := REST_HTTP_TransportType + transportInfo := TransportInfo{ + Id: "sandboxTransport", + Name: "REST", + Type_: &transportType, + Protocol: "HTTP", + Version: "2.0", + Endpoint: &endpoint, + } + var transportInfoResp []TransportInfo + transportInfoResp = append(transportInfoResp, transportInfo) + + // Prepare & send response + jsonResponse, err := json.Marshal(transportInfoResp) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, string(jsonResponse)) +} + +// Delete App services subscriptions +func DeleteServiceSubscriptions(appId string) error { + log.Info("DeleteServiceSubscriptions: ", appId) + + // Get App instance info + appInfo, err := getAppInfo(appId) + if err != nil { + log.Error(err.Error()) + return err + } + + // Validate App info + _, _, err = validateAppInfo(appInfo) + if err != nil { + log.Error(err.Error()) + return err + } + + // Delete app support subscriptions + err = subMgr.DeleteFilteredSubscriptions(appId, SER_AVAILABILITY_NOTIF_SUB_TYPE) + if err != nil { + log.Error(err.Error()) + return err + } + return nil +} + +// Delete App services +func DeleteServices(appId string) error { + log.Debug(">>> DeleteServices: ", appId) + + // Get App instance info + appInfo, err := getAppInfo(appId) + if err != nil { + log.Error(err.Error()) + return err + } + + // Validate App info + _, _, err = validateAppInfo(appInfo) + if err != nil { + log.Error(err.Error()) + return err + } + + // Get Service list + key := baseKey + "app:" + appId + ":svc:*" + err = rc.ForEachJSONEntry(key, deleteService, appId) + if err != nil { + log.Error(err.Error()) + return err + } + return nil +} + +func deleteService(key string, sInfoJson string, data interface{}) error { + log.Debug(">>> DeleteService: key: ", key) + log.Debug(">>> DeleteService: sInfoJson: ", sInfoJson) + + // Get App instance ID from user data + appId := data.(string) + if appId == "" { + return errors.New("appInstanceId not found") + } + + // Delete entry + err := rc.JSONDelEntry(key, ".") + if err != nil { + log.Error(err.Error()) + return err + } + + // Get service information + sInfo := convertJsonToServiceInfo(sInfoJson) + + // Notify remote listeners (except if global instance) + changeType := REMOVED_ServiceAvailabilityNotificationChangeType + if mepName != globalMepName { + sendSvcUpdateMsg(sInfoJson, appId, mepName, string(changeType)) + } + + // Send local service availability notifications + checkSerAvailNotification(sInfo, mepName, changeType) + + return nil +} + +func delServiceById(appId string, svcId string) error { + key := baseKey + "app:" + appId + ":svc:" + svcId + err := rc.JSONDelEntry(key, ".") + if err != nil { + return err + } + + // Delete Liveness timer is any + if _, ok := livenessTimerList[svcId]; ok { + deleteLivenessTicker(svcId) + } + + return nil +} + +func setService(appId string, sInfo *ServiceInfo, changeType ServiceAvailabilityNotificationChangeType) (err error, retCode int) { + // Create/update service + sInfoJson := convertServiceInfoToJson(sInfo) + key := baseKey + "app:" + appId + ":svc:" + sInfo.SerInstanceId + err = rc.JSONSetEntry(key, ".", sInfoJson) + if err != nil { + return err, http.StatusInternalServerError + } + + // Notify remote listeners (except if global instance) + if mepName != globalMepName { + sendSvcUpdateMsg(sInfoJson, appId, mepName, string(changeType)) + } + + // Send local service availability notifications + checkSerAvailNotification(sInfo, mepName, changeType) + + // Set Liveness mechanism if required + if sInfo.LivenessInterval == 0 { // Liveness interval was ommitted + if _, ok := livenessTimerList[sInfo.SerInstanceId]; ok { + deleteLivenessTicker(sInfo.SerInstanceId) + } + } else { // Liveness interval was set + if _, ok := livenessTimerList[sInfo.SerInstanceId]; ok { // An entry already exist, update it + updateLivenessTicker(*sInfo) + } else { // Create new entry + createLivenessTicker(*sInfo) + } + } + + return nil, http.StatusOK +} + +func getServiceById(appId string, svcId string) (string, error) { + key := baseKey + "app:" + appId + ":svc:" + svcId + sInfoJson, err := rc.JSONGetEntry(key, ".") + if err != nil { + return "", err + } + if sInfoJson == "" { + return "", errors.New("Service info not found") + } + return sInfoJson, nil +} + +type QueryParam struct { + Target string `json:"target"` + Value string `json:"value"` +} + +func parseJSONQueryParam(param string) (QueryParam, error) { + var qp QueryParam + err := json.Unmarshal([]byte(param), &qp) + return qp, err +} +func getServices(w http.ResponseWriter, r *http.Request, appId string) { + // Validate query parameters + u, _ := url.Parse(r.URL.String()) + q := u.Query() + validParams := []string{"vend-spec-etsi-mec-serinstance-id", "api-name", "vend-spec-etsi-mec-sercategory-id", "vend-spec-etsi-mec-consumed-local-only", "vend-spec-etsi-mec-is-local", "vend-spec-etsi-mec-scope-of-locality"} + err := validateQueryParams(q, validParams) + if err != nil { + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + + // Extract and parse query parameters + serInstanceIdParam := q.Get("vend-spec-etsi-mec-serinstance-id") + var serInstanceId []string + if serInstanceIdParam != "" { + parsedParam, err := parseJSONQueryParam(serInstanceIdParam) + if err != nil { + errHandlerProblemDetails(w, "Invalid JSON in ser_instance_id", http.StatusBadRequest) + return + } + serInstanceId = append(serInstanceId, parsedParam.Value) + } + + serName := q["api-name"] + // var serName []string + // if serNameParam != "" { + // parsedParam, err := parseJSONQueryParam(serNameParam) + // if err != nil { + // errHandlerProblemDetails(w, "Invalid JSON in ser_name", http.StatusBadRequest) + // return + // } + // serName = append(serName, parsedParam.Value) + // } + + serCategoryIdParam := q.Get("vend-spec-etsi-mec-sercategory-id") + var serCategoryId string + if serCategoryIdParam != "" { + parsedParam, err := parseJSONQueryParam(serCategoryIdParam) + if err != nil { + errHandlerProblemDetails(w, "Invalid JSON in ser_category_id", http.StatusBadRequest) + return + } + serCategoryId = parsedParam.Value + } + + consumedLocalOnlyParam := q.Get("vend-spec-etsi-mec-consumed-local-only") + var consumedLocalOnly bool + var consumedLocalOnlyPresent bool + if consumedLocalOnlyParam != "" { + parsedParam, err := parseJSONQueryParam(consumedLocalOnlyParam) + if err != nil { + errHandlerProblemDetails(w, "Invalid JSON in consumed_local_only", http.StatusBadRequest) + return + } + consumedLocalOnly, err = strconv.ParseBool(parsedParam.Value) + consumedLocalOnlyPresent = true + if err != nil { + consumedLocalOnly = false + consumedLocalOnlyPresent = false + } + + } + + isLocalParam := q.Get("vend-spec-etsi-mec-is-local") + var isLocal bool + var isLocalPresent bool + if isLocalParam != "" { + parsedParam, err := parseJSONQueryParam(isLocalParam) + if err != nil { + errHandlerProblemDetails(w, "Invalid JSON in is_local", http.StatusBadRequest) + return + } + isLocal, err = strconv.ParseBool(parsedParam.Value) + isLocalPresent = true + if err != nil { + isLocal = false + isLocalPresent = false + } + } + + scopeOfLocalityParam := q.Get("vend-spec-etsi-mec-scope-of-locality") + var scopeOfLocality string + if scopeOfLocalityParam != "" { + parsedParam, err := parseJSONQueryParam(scopeOfLocalityParam) + if err != nil { + errHandlerProblemDetails(w, "Invalid JSON in scope_of_locality", http.StatusBadRequest) + return + } + scopeOfLocality = parsedParam.Value + } + + // Make sure only 1 or none of the following are present: ser_instance_id, ser_name, ser_category_id + err = validateServiceQueryParams(serInstanceId, serName, serCategoryId) + if err != nil { + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + + // Retrieve all matching services + sInfoList := &ServiceInfoList{ + ConsumedLocalOnlyPresent: consumedLocalOnlyPresent, + IsLocalPresent: isLocalPresent, + Filters: &FilterParameters{ + serInstanceId: serInstanceId, + serName: serName, + serCategoryId: serCategoryId, + consumedLocalOnly: consumedLocalOnly, + isLocal: isLocal, + scopeOfLocality: scopeOfLocality, + }, + Services: make([]ServiceInfo, 0), + } + + var key string + if appId == "" { + key = baseKeyAnyMep + "app:*:svc:*" + } else { + key = baseKeyAnyMep + "app:" + appId + ":svc:*" + } + + err = rc.ForEachJSONEntry(key, populateServiceInfoList, sInfoList) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + + // Map ServiceInfoList to ServiceApiDescription list + serviceApiDescriptions := make([]ServiceApiDescription, 0) + for _, service := range sInfoList.Services { + apiDesc := ServiceApiDescription{ + ApiName: service.SerName, + ApiId: service.SerInstanceId, + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + Serializer: service.Serializer, + State: service.State, + ScopeOfLocality: service.ScopeOfLocality, + ConsumedLocalOnly: service.ConsumedLocalOnly, + IsLocal: service.IsLocal, + Category: service.SerCategory, + }, + } + serviceApiDescriptions = append(serviceApiDescriptions, apiDesc) + } + + // Prepare & send response + jsonResponse, err := json.Marshal(serviceApiDescriptions) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, string(jsonResponse)) +} + +func getService(w http.ResponseWriter, r *http.Request, appId string, serviceId string) { + // Validate input params + if serviceId == "" { + errStr := "Invalid Service ID" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusInternalServerError) + return + } + + // Retrieve all matching services + var sInfoList ServiceInfoList + + var key string + if appId == "" { + key = baseKeyAnyMep + "app:*:svc:" + serviceId + } else { + key = baseKeyAnyMep + "app:" + appId + ":svc:" + serviceId + } + + err := rc.ForEachJSONEntry(key, populateServiceInfoList, &sInfoList) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + + // Validate result + if len(sInfoList.Services) == 0 { + w.WriteHeader(http.StatusNotFound) + return + } + + // Prepare & send response + jsonResponse, err := json.Marshal(sInfoList.Services[0]) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, string(jsonResponse)) +} + +func populateServiceInfoList(key string, jsonInfo string, sInfoList interface{}) error { + // Get query params & userlist from user data + data := sInfoList.(*ServiceInfoList) + if data == nil { + return errors.New("ServiceInfoList not found") + } + + // Retrieve user info from DB + var sInfo ServiceInfo + err := json.Unmarshal([]byte(jsonInfo), &sInfo) + if err != nil { + return err + } + + // Set IsLocal flag + if mepName == globalMepName { + sInfo.IsLocal = true + } else { + // Get service MEP Name + mep := getMepNameFromKey(key) + + // Check if service is local + if *sInfo.ScopeOfLocality == MEC_SYSTEM_LocalityType || (mep != "" && mep == mepName) { + sInfo.IsLocal = true + } else { + sInfo.IsLocal = false + } + } + + // Filter out non-local services with "consumedLocalOnly" flag set to "true" + if !sInfo.IsLocal && sInfo.ConsumedLocalOnly { + return nil + } + + // Filter services + if data.Filters != nil { + + // Service instance ID + if len(data.Filters.serInstanceId) > 0 { + found := false + for _, value := range data.Filters.serInstanceId { + if sInfo.SerInstanceId == value { + found = true + break + } + } + if !found { + return nil + } + } + + // Service name + if len(data.Filters.serName) > 0 { + found := false + for _, value := range data.Filters.serName { + if sInfo.SerName == value { + found = true + break + } + } + if !found { + return nil + } + } + + // Service category + // NOTE: Compare with either the category name or id, spec is not clear + if data.Filters.serCategoryId != "" { + categoryId := data.Filters.serCategoryId + if sInfo.SerCategory == nil || (categoryId != sInfo.SerCategory.Name && categoryId != sInfo.SerCategory.Id) { + return nil + } + } + + // Scope of Locality + if data.Filters.scopeOfLocality != "" { + if data.Filters.scopeOfLocality != string(*sInfo.ScopeOfLocality) { + return nil + } + } + + // Service consumed local only + if data.ConsumedLocalOnlyPresent { + if data.Filters.consumedLocalOnly { + if !sInfo.ConsumedLocalOnly { + return nil + } + } else { //data.Filters.consumedLocalOnly is false + if sInfo.ConsumedLocalOnly { + return nil + } + } + } + + // Is local service + if data.IsLocalPresent { + if data.Filters.isLocal { + if !sInfo.IsLocal { + return nil + } + } + } + } + + // Add service to list + data.Services = append(data.Services, sInfo) + return nil +} + +func sendSvcUpdateMsg(sInfoJson, appId, mep, changeType string) { + // Inform other MEP instances + // Send MEC Service Update Notification message on local Message Queue + msg := mqLocal.CreateMsg(mq.MsgMecSvcUpdate, mq.TargetAll, sandboxName) + msg.Payload[fieldSvcInfo] = sInfoJson + msg.Payload[fieldAppId] = appId + msg.Payload[fieldMepName] = mep + msg.Payload[fieldChangeType] = changeType + log.Debug("TX MSG: ", mq.PrintMsg(msg)) + err := mqLocal.SendMsg(msg) + if err != nil { + log.Error("Failed to send message. Error: ", err.Error()) + } +} + +func processSvcUpdate(sInfoJson, mep, changeType string) { + // Ignore updates for global MEP instance + if mepName == globalMepName { + log.Warn("Ignoring service update received at global instance") + return + } + // Ignore local MEP updates (already processed) + if mep == mepName { + return + } + + // Unmarshal received service info + sInfo := convertJsonToServiceInfo(sInfoJson) + + // Check if notifications must be sent + checkSerAvailNotification(sInfo, mep, ServiceAvailabilityNotificationChangeType(changeType)) +} + +func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType ServiceAvailabilityNotificationChangeType) { + // Set IsLocal flag + if *sInfo.ScopeOfLocality == MEC_SYSTEM_LocalityType || (mep != "" && mep == mepName) { + sInfo.IsLocal = true + } else { + sInfo.IsLocal = false + } + + // Filter out non-local services with "consumedLocalOnly" flag set to "true" + if !sInfo.IsLocal && sInfo.ConsumedLocalOnly { + return + } + + // Get subscriptions with matching type + subList, err := subMgr.GetFilteredSubscriptions("", SER_AVAILABILITY_NOTIF_SUB_TYPE) + if err != nil { + log.Error("Failed to get subscription list with err: ", err.Error()) + return + } + + // Process service availability notification + for _, sub := range subList { + + // Unmarshal original JSON subscription + origSub := convertJsonToSerAvailabilityNotifSub(sub.JsonSubOrig) + if origSub == nil { + continue + } + + // Check subscription filter criteria + if origSub.FilteringCriteria != nil { + + // Service Instance IDs + if origSub.FilteringCriteria.SerInstanceIds != nil && len(origSub.FilteringCriteria.SerInstanceIds) > 0 { + found := false + for _, serInstanceId := range origSub.FilteringCriteria.SerInstanceIds { + if serInstanceId == sInfo.SerInstanceId { + found = true + break + } + } + if !found { + continue + } + } + + // Service Names + if origSub.FilteringCriteria.SerNames != nil && len(origSub.FilteringCriteria.SerNames) > 0 { + found := false + for _, serName := range origSub.FilteringCriteria.SerNames { + if serName == sInfo.SerName { + found = true + break + } + } + if !found { + continue + } + } + + // Service Categories + if origSub.FilteringCriteria.SerCategories != nil && len(origSub.FilteringCriteria.SerCategories) > 0 { + found := false + for _, serCategory := range origSub.FilteringCriteria.SerCategories { + if serCategory.Href == sInfo.SerCategory.Href && + serCategory.Id == sInfo.SerCategory.Id && + serCategory.Name == sInfo.SerCategory.Name && + serCategory.Version == sInfo.SerCategory.Version { + found = true + break + } + } + if !found { + continue + } + } + + // Service states + if origSub.FilteringCriteria.States != nil && len(origSub.FilteringCriteria.States) > 0 { + found := false + for _, serState := range origSub.FilteringCriteria.States { + if serState == *sInfo.State { + found = true + break + } + } + if !found { + continue + } + } + + // Service locality + if origSub.FilteringCriteria.IsLocal && !sInfo.IsLocal { + continue + } + } + + // Create notification payload + notif := &ServiceAvailabilityNotification{ + NotificationType: SER_AVAILABILITY_NOTIF_TYPE, + Links: &Subscription{ + Subscription: &LinkType{ + Href: sub.Cfg.Self, + }, + }, + } + serAvailabilityRef := ServiceAvailabilityNotificationServiceReferences{ + Link: &LinkType{ + Href: hostUrl.String() + basePath + "services/" + sInfo.SerInstanceId, + }, + SerName: sInfo.SerName, + SerInstanceId: sInfo.SerInstanceId, + State: sInfo.State, + ChangeType: &changeType, + } + notif.ServiceReferences = append(notif.ServiceReferences, serAvailabilityRef) + + // Send notification + go func(sub *subs.Subscription) { + log.Info("Sending Service Availability notification (" + sub.Cfg.Id + ") for " + string(changeType)) + err := subMgr.SendNotification(sub, []byte(convertServiceAvailabilityNotifToJson(notif))) + if err != nil { + log.Error("Failed to send Service Availability notif with err: ", err.Error()) + } + }(sub) + } +} + +func validateQueryParams(params url.Values, validParams []string) error { + for param := range params { + found := false + for _, validParam := range validParams { + if param == validParam { + found = true + break + } + } + if !found { + err := errors.New("Invalid query param: " + param) + log.Error(err.Error()) + return err + } + } + return nil +} + +func validateServiceQueryParams(serInstanceId []string, serName []string, serCategoryId string) error { + count := 0 + if len(serInstanceId) > 0 { + count++ + } + if len(serName) > 0 { + count++ + } + if serCategoryId != "" { + count++ + } + if count > 1 { + err := errors.New("Either \"ser_instance_id\" or \"ser_name\" or \"ser_category_id\" or none of them shall be present") + log.Error(err.Error()) + return err + } + return nil +} + +func getMepNameFromKey(key string) string { + fields := strings.Split(strings.TrimPrefix(key, dkm.GetKeyRoot(sandboxName)+appEnablementKey+":mep:"), ":") + if len(fields) > 0 { + return fields[0] + } + return "" +} + +func getAppInfo(appId string) (map[string]string, error) { + var appInfo map[string]string + + // Get app instance from local MEP only + key := baseKey + "app:" + appId + ":info" + appInfo, err := rc.GetEntry(key) + if err != nil || len(appInfo) == 0 { + return nil, errors.New("App Instance not found") + } + return appInfo, nil +} + +func getAppInfoAnyMep(appId string) (map[string]string, error) { + var appInfoList []map[string]string + + // Get app instance from any MEP + keyMatchStr := baseKeyAnyMep + "app:" + appId + ":info" + err := rc.ForEachEntry(keyMatchStr, populateAppInfo, &appInfoList) + if err != nil || len(appInfoList) != 1 { + return nil, errors.New("App Instance not found") + } + return appInfoList[0], nil +} + +func populateAppInfo(key string, entry map[string]string, userData interface{}) error { + appInfoList := userData.(*[]map[string]string) + + // Copy entry + appInfo := make(map[string]string, len(entry)) + for k, v := range entry { + appInfo[k] = v + } + + // Add app info to list + *appInfoList = append(*appInfoList, appInfo) + return nil +} + +func validateAppInfo(appInfo map[string]string) (int, string, error) { + // Make sure App is in ready state + if appInfo[fieldState] != APP_STATE_READY { + var problemDetails ProblemDetails + problemDetails.Status = http.StatusForbidden + problemDetails.Detail = "App Instance not ready. Waiting for AppReadyConfirmation." + return http.StatusForbidden, convertProblemDetailsToJson(&problemDetails), errors.New("App Instance not ready") + } + return http.StatusOK, "", nil +} + +func validateCategoryRef(categoryRef *CategoryRef) string { + if categoryRef != nil { + if categoryRef.Href == "" { + return "CategoryRef mandatory parameter Href missing." + } + if categoryRef.Id == "" { + return "CategoryRef mandatory parameter Id missing." + } + if categoryRef.Name == "" { + return "CategoryRef mandatory parameter Name missing." + } + if categoryRef.Version == "" { + return "CategoryRef mandatory parameter Version missing." + } + } + return "" +} + +func newSerAvailabilityNotifSubCfg(sub *SerAvailabilityNotificationSubscription, subId string, appId string) *subs.SubscriptionCfg { + subCfg := &subs.SubscriptionCfg{ + Id: subId, + AppId: appId, + Type: SER_AVAILABILITY_NOTIF_SUB_TYPE, + Self: sub.Links.Self.Href, + NotifyUrl: sub.CallbackReference, + ExpiryTime: nil, + PeriodicInterval: 0, + RequestTestNotif: false, + RequestWebsocketUri: false, + } + return subCfg +} + +func errHandlerProblemDetails(w http.ResponseWriter, error string, code int) { + var pd ProblemDetails + pd.Detail = error + pd.Status = int32(code) + + jsonResponse := convertProblemDetailstoJson(&pd) + + w.WriteHeader(code) + fmt.Fprint(w, jsonResponse) +} diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 55c631302..88a68f97a 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -32,6 +32,7 @@ import ( met "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-metrics" appSupport "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-app-enablement/server/app-support" + capifMgmt "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-app-enablement/server/capif-mgmt" svcMgmt "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-app-enablement/server/service-mgmt" "github.com/gorilla/mux" @@ -321,6 +322,18 @@ var routes = Routes{ svcMgmt.TransportsGET, }, + Route{ + "Index", + "GET", + "/service-apis/v1/", + Index, + }, + Route{ + "ServicesGET", + strings.ToUpper("Get"), + "/service-apis/v1/allServiceAPIs", + capifMgmt.ServicesGET, + }, Route{ "Index", "GET", diff --git a/go-apps/meep-app-enablement/server/service-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/service-mgmt/service-mgmt.go index 64d61e75e..63ea3ab6f 100644 --- a/go-apps/meep-app-enablement/server/service-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/service-mgmt/service-mgmt.go @@ -45,7 +45,7 @@ const SER_AVAILABILITY_NOTIF_SUB_TYPE = "SerAvailabilityNotificationSubscription const SER_AVAILABILITY_NOTIF_TYPE = "SerAvailabilityNotification" const APP_STATE_READY = "READY" -//const logModuleAppEnablement = "meep-app-enablement" +// const logModuleAppEnablement = "meep-app-enablement" const serviceName = "App Enablement Service" // App Info fields diff --git a/go-packages/meep-capif-mgmt-client/.gitignore b/go-packages/meep-capif-mgmt-client/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/go-packages/meep-capif-mgmt-client/.swagger-codegen-ignore b/go-packages/meep-capif-mgmt-client/.swagger-codegen-ignore new file mode 100644 index 000000000..c5fa491b4 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/go-packages/meep-capif-mgmt-client/.swagger-codegen/VERSION b/go-packages/meep-capif-mgmt-client/.swagger-codegen/VERSION new file mode 100644 index 000000000..243661b35 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/.swagger-codegen/VERSION @@ -0,0 +1 @@ +3.0.59 \ No newline at end of file diff --git a/go-packages/meep-capif-mgmt-client/.travis.yml b/go-packages/meep-capif-mgmt-client/.travis.yml new file mode 100644 index 000000000..f5cb2ce9a --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/.travis.yml @@ -0,0 +1,8 @@ +language: go + +install: + - go get -d -v . + +script: + - go build -v ./ + diff --git a/go-packages/meep-capif-mgmt-client/README.md b/go-packages/meep-capif-mgmt-client/README.md new file mode 100644 index 000000000..a683dc75c --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/README.md @@ -0,0 +1,59 @@ +# Go API client for swagger + +The ETSI MEC ISG MEC011 MEC Service Management realized by CAPIF APIs described using OpenAPI + +## Overview +This API client was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [swagger-spec](https://github.com/swagger-api/swagger-spec) from a remote server, you can easily generate an API client. + +- API version: 3.2.1 +- Package version: 1.0.0 +- Build package: io.swagger.codegen.v3.generators.go.GoClientCodegen + +## Installation +Put the package under your project folder and add the following in import: +```golang +import "./swagger" +``` + +## Documentation for API Endpoints + +All URIs are relative to *https://localhost/sandboxname/service-apis/v1* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*AppServicesApi* | [**AppServicesGET**](docs/AppServicesApi.md#appservicesget) | **Get** /{apfId}/service-apis | get services +*AppServicesApi* | [**AppServicesPOST**](docs/AppServicesApi.md#appservicespost) | **Post** /{apfId}/service-apis | Publish a new API +*AppServicesApi* | [**AppServicesServiceIdDELETE**](docs/AppServicesApi.md#appservicesserviceiddelete) | **Delete** /{apfId}/service-apis/{serviceApiId} | +*AppServicesApi* | [**AppServicesServiceIdGET**](docs/AppServicesApi.md#appservicesserviceidget) | **Get** /{apfId}/service-apis/{serviceApiId} | +*AppServicesApi* | [**AppServicesServiceIdPATCH**](docs/AppServicesApi.md#appservicesserviceidpatch) | **Patch** /{apfId}/service-apis/{serviceApiId} | +*AppServicesApi* | [**AppServicesServiceIdPUT**](docs/AppServicesApi.md#appservicesserviceidput) | **Put** /{apfId}/service-apis/{serviceApiId} | +*AppSubscriptionsApi* | [**ApplicationsSubscriptionDELETE**](docs/AppSubscriptionsApi.md#applicationssubscriptiondelete) | **Delete** /{subscriberId}/subscriptions/{subscriptionId} | Delete an existing CAPIF Event Subscription +*AppSubscriptionsApi* | [**ApplicationsSubscriptionPatch**](docs/AppSubscriptionsApi.md#applicationssubscriptionpatch) | **Patch** /{subscriberId}/subscriptions/{subscriptionId} | Modify an existing CAPIF Event Subscription +*AppSubscriptionsApi* | [**ApplicationsSubscriptionsPOST**](docs/AppSubscriptionsApi.md#applicationssubscriptionspost) | **Post** /{subscriberId}/subscriptions | Create a new CAPIF Events Subscription +*AppSubscriptionsApi* | [**ApplicationsSubscriptionsPUT**](docs/AppSubscriptionsApi.md#applicationssubscriptionsput) | **Put** /{subscriberId}/subscriptions/{subscriptionId} | The PUT method is used to update an existing subscription resource. +*ServicesApi* | [**ServicesGET**](docs/ServicesApi.md#servicesget) | **Get** /allServiceAPIs | + +## Documentation For Models + + - [CapifEvent](docs/CapifEvent.md) + - [CategoryRef](docs/CategoryRef.md) + - [DiscoveredApis](docs/DiscoveredApis.md) + - [EventNotification](docs/EventNotification.md) + - [EventSubscription](docs/EventSubscription.md) + - [EventSubscriptionPatch](docs/EventSubscriptionPatch.md) + - [LocalityType](docs/LocalityType.md) + - [MecServiceInfoCapifExt](docs/MecServiceInfoCapifExt.md) + - [MecServiceInfoCapifExtPatch](docs/MecServiceInfoCapifExtPatch.md) + - [ProblemDetails](docs/ProblemDetails.md) + - [SerializerType](docs/SerializerType.md) + - [ServiceApiDescription](docs/ServiceApiDescription.md) + - [ServiceApiDescriptionPatch](docs/ServiceApiDescriptionPatch.md) + - [ServiceState](docs/ServiceState.md) + +## Documentation For Authorization + Endpoints do not require authorization. + + +## Author + +cti_support@etsi.org diff --git a/go-packages/meep-capif-mgmt-client/api/swagger.yaml b/go-packages/meep-capif-mgmt-client/api/swagger.yaml new file mode 100644 index 000000000..6a0c250d0 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/api/swagger.yaml @@ -0,0 +1,1386 @@ +openapi: 3.0.0 +info: + title: MEC service management realized by CAPIF APIs + description: The ETSI MEC ISG MEC011 MEC Service Management realized by CAPIF APIs + described using OpenAPI + contact: + email: cti_support@etsi.org + license: + name: BSD-3-Clause + url: https://forge.etsi.org/legal-matters + version: 3.2.1 +externalDocs: + description: "ETSI GS MEC011 Application Enablement API, V3.2.1" + url: https://www.etsi.org/deliver/etsi_gs/MEC/001_099/011/03.02.01_60/gs_mec011v030201p.pdf +servers: +- url: https://localhost/sandboxname/service-apis/v1 + description: Service APIs +- url: https://localhost/sandboxname/published-apis/v1 + description: Published APIs +- url: https://localhost/sandboxname/capif-events/v1 + description: CAPIF Events APIs +tags: +- name: services +- name: appServices +- name: appSubscriptions +- name: callbacks +paths: + /allServiceAPIs: + get: + tags: + - services + description: This method retrieves information about a list of mecService resources. + This method is typically used in "service availability query" procedure + operationId: Services_GET + parameters: + - name: vend-spec-etsi-mec-serinstance-id + in: query + description: Vendor-specific query parameter for service instance ID. The + "target" attribute shall be set to "/apiId". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/apiId\", \"value\": \"serviceInstanceId\"}" + - name: api-name + in: query + description: "This query parameter corresponds to the parameter \"ser_name\"\ + \ as defined in clause 8.2.3.3.1. As opposed to the cardinality of ser_instance_id\ + \ defined in clause 8.2.3.3.1 that is 0..N, this parameter only supports\ + \ a cardinality of 0..1." + required: false + style: form + explode: true + schema: + type: array + items: + type: string + - name: api-invoker-id + in: query + description: "If the Discover_Service_API is produced by the MEC platform\ + \ towards the MEC applications, this identifier shall be set to the value\ + \ of the \"appInstanceId\" (see clause 7.1.2.6). If the Discover_Service_API\ + \ is produced by the CCF, the provisions in clause 8.1.2.2.3.1 of 3GPP TS\ + \ 29.222 [21] apply. " + required: false + style: form + explode: true + schema: + type: string + - name: vend-spec-etsi-mec-sercategory-id + in: query + description: Vendor-specific query parameter for service category ID. The + "target" attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id\"\ + , \"value\": \"serviceCategoryId\"}" + - name: vend-spec-etsi-mec-consumed-local-only + in: query + description: Vendor-specific query parameter for consumed local only. The + "target" attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly\"\ + , \"value\": \"true\"}" + - name: vend-spec-etsi-mec-is-local + in: query + description: Vendor-specific query parameter for is local. The "target" attribute + shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal\"\ + , \"value\": \"true\"}" + - name: vend-spec-etsi-mec-scope-of-locality + in: query + description: Vendor-specific query parameter for scope of locality. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality\"\ + , \"value\": \"scopeOfLocalityValue\"}" + responses: + "200": + description: | + The response body contains the result of the search over the list of registered APIs. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DiscoveredAPIs' + x-content-type: application/json + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: Contains an alternative target URI of the resource located + in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: Contains an alternative target URI of the resource located + in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "414": + description: It is used to indicate that the server is refusing to process + the request because the request URI is longer than the server is willing + or able to process. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + servers: + - url: https://localhost/sandboxname/service-apis/v1 + /{apfId}/service-apis: + get: + tags: + - appServices + summary: get services + description: This method retrieves information about a list of mecService resources. + This method is typically used in "service availability query" procedure + operationId: AppServices_GET + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + responses: + "200": + description: | + Successful case. The representation(s) of the "Individual APF published API" resource(s) of the requested service API(s) shall be returned in the response body. If there are no active "Individual APF published API" resources at the CCF, an empty array is returned. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + post: + tags: + - appServices + summary: Publish a new API + description: Enables a service consumer to request to publish a new API at the + CCF. + operationId: AppServices_POST + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescription' + required: true + responses: + "201": + description: | + Successful case. The service API is successfully published. The URI of the created "Individual APF published API" resource shall be returned in an HTTP "Location" header. + headers: + Location: + description: | + Contains the URI of the newly created resource, according to the structure: {apiRoot}/published-apis//{apfId}/service-apis/{serviceApiId} + style: simple + explode: false + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescription' + servers: + - url: https://localhost/sandboxname/published-apis/v1 + /{apfId}/service-apis/{serviceApiId}: + get: + tags: + - appServices + description: The HTTP GET method allows a service consumer to retrieve an existing + "Individual APF published API" resource at the CCF. + operationId: AppServicesServiceId_GET + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + responses: + "200": + description: | + Successful case. The service API is successfully published and a representation of the created "Individual APF published API" resource shall be returned. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + put: + tags: + - appServices + description: The HTTP PUT method allows a service consumer to update an existing + "Individual APF published API" resource at the CCF. + operationId: AppServicesServiceId_PUT + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescription' + required: true + responses: + "200": + description: | + Successful case. The service API is successfully published and a representation of the created "Individual APF published API" resource shall be returned. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "204": + description: Successful case. The "Individual APF published API" resource + is successfully updated and no content is returned in the response body. + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "412": + description: "Precondition Failed. It is used when a condition has failed\ + \ during conditional requests, e.g. when using ETags to avoid write conflicts." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + delete: + tags: + - appServices + description: The HTTP DELETE method allows a service consumer to delete an existing + "Individual APF published API" resource at the CCF + operationId: AppServicesServiceId_DELETE + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + responses: + "204": + description: Successful case. The "Individual APF published API" resource + is successfully deleted. + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + patch: + tags: + - appServices + description: The HTTP PATCH method allows a service consumer to modify an existing + "Individual APF published API" resource at the CCF. + operationId: AppServicesServiceId_PATCH + parameters: + - name: apfId + in: path + description: "Identifier of the entity that registers the service API. If\ + \ the MEC app plays the role of the APF, this variable shall be set to the\ + \ value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform\ + \ plays the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + - name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceAPIDescriptionPatch' + required: true + responses: + "200": + description: "Successful case. The \"Individual APF published API\"\n resource\ + \ is successfully modified and a representation of \n the updated resource\ + \ shall be returned in the response \n body.\n" + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + x-content-type: application/json + "204": + description: Successful case. The "Individual APF published API" resource + is successfully updated and no content is returned in the response body. + "307": + description: | + Temporary redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "308": + description: | + Permanent redirection. The response shall include a Location header field containing an alternative target URI of the resource located in an alternative CCF. + headers: + Location: + description: | + Contains an alternative target URI of the resource located in an alternative CCF. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "412": + description: "Precondition Failed. It is used when a condition has failed\ + \ during conditional requests, e.g. when using ETags to avoid write conflicts." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + servers: + - url: https://localhost/sandboxname/published-apis/v1 + /{subscriberId}/subscriptions: + post: + tags: + - appSubscriptions + summary: Create a new CAPIF Events Subscription + description: Create a new CAPIF Events Subscription resource. + operationId: ApplicationsSubscriptions_POST + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + required: true + responses: + "201": + description: | + CAPIF Events Subscription resource created successfully. The URI of the created resource shall be returned in the "Location" HTTP header + headers: + Location: + description: | + Contains the URI of the newly created resource, according to the structure: {apiRoot}/capif-events//{subscriberId}/subscriptions/{subscriptionId} + style: simple + explode: false + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + callbacks: + EventNotification: + '{$request.body#/callbackReference}': + post: + tags: + - callbacks + summary: Create callback + description: "The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE,\ + \ and SERVICE_API_UPDATE defined in the type \"CAPIFEvent\" shall\ + \ be supported. The remaining values of that type need not be supported." + operationId: EventNotification_POST + requestBody: + $ref: '#/components/requestBodies/EventNotification' + responses: + "204": + description: ' The receipt of the Notification is acknowledged.' + deprecated: false + servers: + - url: https://localhost/sandboxname/capif-events/v1 + '/{subscriberId}/subscriptions/{subscriptionId} ': + put: + tags: + - appSubscriptions + summary: The PUT method is used to update an existing subscription resource. + description: The susbcribing entity shall initiate the HTTP PUT request message + and the CAPIF core function shall respond to the message. + operationId: ApplicationsSubscriptions_PUT + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + - name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + required: true + responses: + "200": + description: "The event subscription was successfully updated, and a representation\ + \ of the updated resource is returned." + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + "204": + description: The event subscription was successfully updated and no content + is returned in the response body. + "307": + description: Temporary redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + "308": + description: Permanent redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. It is used to indicate that incorrect parameters + were passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + delete: + tags: + - appSubscriptions + summary: Delete an existing CAPIF Event Subscription + description: This endpoint deletes an existing CAPIF Event Subscription resource. + operationId: ApplicationsSubscription_DELETE + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + - name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + responses: + "204": + description: The individual CAPIF Events Subscription matching the subscriptionId + is deleted. + "307": + description: "Temporary redirection, during resource termination. The response\ + \ shall include a Location header field containing an alternative URI\ + \ of the resource located in an alternative CAPIF core function." + headers: + Location: + description: An alternative URI of the resource located in an alternative + CAPIF core function. + style: simple + explode: false + schema: + type: string + "308": + description: "Permanent redirection, during resource termination. The response\ + \ shall include a Location header field containing an alternative URI\ + \ of the resource located in an alternative CAPIF core function." + headers: + Location: + description: An alternative URI of the resource located in an alternative + CAPIF core function. + style: simple + explode: false + schema: + type: string + "400": + description: Bad Request. The request was invalid or cannot be served. The + exact error should be explained in the error payload. + "401": + description: Unauthorized. The request requires user authentication. + "403": + description: Forbidden. The server understood the request but refuses to + authorize it. + "404": + description: Not Found. The server has not found anything matching the Request-URI. + "500": + description: Internal Server Error. The server encountered an unexpected + condition which prevented it from fulfilling the request. + patch: + tags: + - appSubscriptions + summary: Modify an existing CAPIF Event Subscription + description: This endpoint modifies an existing CAPIF Event Subscription resource. + operationId: ApplicationsSubscription_patch + parameters: + - name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + - name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscriptionPatch' + required: true + responses: + "200": + description: The subscription was successfully modified and a representation + of the updated resource is returned in the response body. + content: + application/json: + schema: + $ref: '#/components/schemas/EventSubscription' + "204": + description: The subscription was successfully modified and no content was + returned in the response body. + "307": + description: Temporary redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + "308": + description: Permanent redirection. The response shall include a Location + header field containing an alternative URI of the resource located in + an alternative CAPIF core function. + headers: + Location: + description: Contains an alternative URI of the resource located in + an alternative CAPIF core function. + style: simple + explode: false + schema: + type: string + servers: + - url: https://localhost/sandboxname/capif-events/v1 +components: + schemas: + EventSubscriptionPatch: + required: + - events + type: object + properties: + events: + type: array + description: | + The events for which the subscription is modified. + items: + $ref: '#/components/schemas/CAPIFEvent' + notificationDestination: + type: string + description: | + URI to which notifications will be sent. Shall be set to the value of the "callbackReference" attribute in the "SerAvailabilityNotificationSubscription" structure. + format: uri + EventSubscription: + required: + - events + - notificationDestination + type: object + properties: + events: + type: array + items: + $ref: '#/components/schemas/CAPIFEvent' + notificationDestination: + type: string + description: | + URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response. + format: uri + requestTestNotification: + type: boolean + websocketNotifConfig: + type: string + example: + notificationDestination: http://example.com/aeiou + websocketNotifConfig: websocketNotifConfig + events: + - SERVICE_API_AVAILABLE + - SERVICE_API_AVAILABLE + requestTestNotification: true + CAPIFEvent: + type: string + description: | + The CAPIFEvent data type represents the type of events for which the subscription is made. + enum: + - SERVICE_API_AVAILABLE + - SERVICE_API_UNAVAILABLE + - SERVICE_API_UPDATE + CategoryRef: + required: + - href + - id + - name + - version + type: object + properties: + href: + type: string + description: Reference of the catalogue + format: uri + id: + type: string + description: Unique identifier of the category + name: + type: string + description: "Name of the category, example values include RNI, Location\ + \ & Bandwidth Management" + version: + type: string + description: Category version + description: This type represents the category reference + example: + name: name + href: http://example.com/aeiou + id: id + version: version + ProblemDetails: + required: + - detail + - status + type: object + properties: + type: + type: string + description: A URI reference according to IETF RFC 3986 that identifies + the problem type + format: uri + title: + type: string + description: "A short, human-readable summary of the problem type" + status: + type: integer + description: The HTTP status code for this occurrence of the problem + format: uint32 + detail: + type: string + description: A human-readable explanation specific to this occurrence of + the problem + instance: + type: string + description: A URI reference that identifies the specific occurrence of + the problem + format: uri + EventNotification: + type: object + properties: + events: + type: array + description: | + The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE, and SERVICE_API_UPDATE defined in the type "CAPIFEvent" shall be supported. The remaining values of that type need not be supported. + items: + $ref: '#/components/schemas/CAPIFEvent' + SerializerType: + type: string + description: | + The enumeration SerializerType represents types of serializers. This enumeration shall be extensible. + enum: + - JSON + - XML + - PROTOBUF3 + LocalityType: + type: string + description: | + The enumeration LocalityType represents types of locality. + enum: + - MEC_SYSTEM + - MEC_HOST + - NFVI_POP + - ZONE + - ZONE_GROUP + - NFVI_NODE + ServiceState: + type: string + description: | + The enumeration ServiceState represents possible states of a MEC service instance. + enum: + - ACTIVE + - INACTIVE + - SUSPENDED + DiscoveredAPIs: + type: object + properties: + serviceAPIDescriptions: + type: array + items: + $ref: '#/components/schemas/ServiceAPIDescription' + example: + serviceAPIDescriptions: + - apiName: apiName + vendorSpecific-urn:etsi:mec:capifext:service-info: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + apiId: apiId + - apiName: apiName + vendorSpecific-urn:etsi:mec:capifext:service-info: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + apiId: apiId + ServiceAPIDescriptionPatch: + type: object + properties: + vendorSpecific-urn:etsi:mec:capifext:service-info: + $ref: '#/components/schemas/MecServiceInfoCapifExtPatch' + ServiceAPIDescription: + type: object + properties: + apiName: + type: string + description: | + Shall be set to the value of the "serName" attribute as defined in clause 8.1.2.2. + apiId: + type: string + description: | + If present, shall be set to the value of the "serInstanceId" attribute as defined in clause 8.1.2.2. + vendorSpecific-urn:etsi:mec:capifext:service-info: + $ref: '#/components/schemas/MecServiceInfoCapifExt' + example: + apiName: apiName + vendorSpecific-urn:etsi:mec:capifext:service-info: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + apiId: apiId + MecServiceInfoCapifExtPatch: + type: object + properties: + serializer: + $ref: '#/components/schemas/SerializerType' + state: + $ref: '#/components/schemas/ServiceState' + scopeOfLocality: + $ref: '#/components/schemas/LocalityType' + consumedLocalOnly: + type: boolean + isLocal: + type: boolean + category: + $ref: '#/components/schemas/CategoryRef' + MecServiceInfoCapifExt: + type: object + properties: + serializer: + $ref: '#/components/schemas/SerializerType' + state: + $ref: '#/components/schemas/ServiceState' + scopeOfLocality: + $ref: '#/components/schemas/LocalityType' + consumedLocalOnly: + type: boolean + isLocal: + type: boolean + category: + $ref: '#/components/schemas/CategoryRef' + example: + scopeOfLocality: MEC_SYSTEM + serializer: JSON + state: ACTIVE + consumedLocalOnly: true + category: + name: name + href: http://example.com/aeiou + id: id + version: version + isLocal: true + responses: + "400": + description: Bad Request. It is used to indicate that incorrect parameters were + passed to the request. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "401": + description: Unauthorized. It is used when the client did not submit the appropriate + credentials. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "403": + description: Forbidden. The operation is not allowed given the current status + of the resource. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "404": + description: Not Found. It is used when a client provided a URI that cannot + be mapped to a valid resource URI. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "409": + description: "Conflict. The operation cannot be executed currently, due to a\ + \ conflict with the state of the resource. Typically, this is because the\ + \ application instance resource is in NOT_INSTANTIATED state." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "412": + description: "Precondition Failed. It is used when a condition has failed during\ + \ conditional requests, e.g. when using ETags to avoid write conflicts." + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "414": + description: It is used to indicate that the server is refusing to process the + request because the request URI is longer than the server is willing or able + to process. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + "429": + description: Too Many Requests. It is used when a rate limiter has triggered. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' + parameters: + Path.apfId: + name: apfId + in: path + description: "Identifier of the entity that registers the service API. If the\ + \ MEC app plays the role of the APF, this variable shall be set to the value\ + \ of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays\ + \ the role of the APF, this variable shall be set to a specific identifier\ + \ that identifies the MEC platform. " + required: true + style: simple + explode: false + schema: + type: string + Path.subscriberId: + name: subscriberId + in: path + description: 'This variable shall be set to the value of the "appInstanceId" + (see clause 7.1.2.6). ' + required: true + style: simple + explode: false + schema: + type: string + Path.SubscriptionId: + name: subscriptionId + in: path + description: Represents a subscription to the notifications from the MEC platform. + required: true + style: simple + explode: false + schema: + type: string + Path.serviceApiId: + name: serviceApiId + in: path + description: Represents a MEC service instance. + required: true + style: simple + explode: false + schema: + type: string + Query.vend-spec-etsi-mec-sercategory-id: + name: vend-spec-etsi-mec-sercategory-id + in: query + description: Vendor-specific query parameter for service category ID. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id\"\ + , \"value\": \"serviceCategoryId\"}" + Query.vend-spec-etsi-mec-serinstance-id: + name: vend-spec-etsi-mec-serinstance-id + in: query + description: Vendor-specific query parameter for service instance ID. The "target" + attribute shall be set to "/apiId". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/apiId\", \"value\": \"serviceInstanceId\"}" + Query.api-name: + name: api-name + in: query + description: "This query parameter corresponds to the parameter \"ser_name\"\ + \ as defined in clause 8.2.3.3.1. As opposed to the cardinality of ser_instance_id\ + \ defined in clause 8.2.3.3.1 that is 0..N, this parameter only supports a\ + \ cardinality of 0..1." + required: false + style: form + explode: true + schema: + type: array + items: + type: string + Query.api-invoker-id: + name: api-invoker-id + in: query + description: "If the Discover_Service_API is produced by the MEC platform towards\ + \ the MEC applications, this identifier shall be set to the value of the \"\ + appInstanceId\" (see clause 7.1.2.6). If the Discover_Service_API is produced\ + \ by the CCF, the provisions in clause 8.1.2.2.3.1 of 3GPP TS 29.222 [21]\ + \ apply. " + required: false + style: form + explode: true + schema: + type: string + Query.vend-spec-etsi-mec-scope-of-locality: + name: vend-spec-etsi-mec-scope-of-locality + in: query + description: Vendor-specific query parameter for scope of locality. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality\"\ + , \"value\": \"scopeOfLocalityValue\"}" + Query.vend-spec-etsi-mec-is-local: + name: vend-spec-etsi-mec-is-local + in: query + description: Vendor-specific query parameter for is local. The "target" attribute + shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal\"\ + , \"value\": \"true\"}" + Query.vend-spec-etsi-mec-consumed-local-only: + name: vend-spec-etsi-mec-consumed-local-only + in: query + description: Vendor-specific query parameter for consumed local only. The "target" + attribute shall be set to "/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly". + required: false + style: form + explode: true + schema: + type: string + example: "{\"target\": \"/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly\"\ + , \"value\": \"true\"}" + requestBodies: + EventNotification: + content: + application/json: + schema: + $ref: '#/components/schemas/EventNotification' + required: true diff --git a/go-packages/meep-capif-mgmt-client/api_services.go b/go-packages/meep-capif-mgmt-client/api_services.go new file mode 100644 index 000000000..545863af4 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/api_services.go @@ -0,0 +1,1272 @@ +/* + * 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 client + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strings" + + "github.com/antihax/optional" +) + +// Linger please +var ( + _ context.Context +) + +type ServicesApiService service + +/* +ServicesApiService +This method retrieves information about a list of mecService resources. This method is typically used in \"service availability query\" procedure + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param optional nil or *ServicesApiServicesGETOpts - Optional Parameters: + * @param "VendSpecEtsiMecSerinstanceId" (optional.String) - Vendor-specific query parameter for service instance ID. The \"target\" attribute shall be set to \"/apiId\". + * @param "ApiName" (optional.Interface of []string) - This query parameter corresponds to the parameter \"ser_name\" as defined in clause 8.2.3.3.1. As opposed to the cardinality of ser_instance_id defined in clause 8.2.3.3.1 that is 0..N, this parameter only supports a cardinality of 0..1. + * @param "ApiInvokerId" (optional.String) - If the Discover_Service_API is produced by the MEC platform towards the MEC applications, this identifier shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the Discover_Service_API is produced by the CCF, the provisions in clause 8.1.2.2.3.1 of 3GPP TS 29.222 [21] apply. + * @param "VendSpecEtsiMecSercategoryId" (optional.String) - Vendor-specific query parameter for service category ID. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id\". + * @param "VendSpecEtsiMecConsumedLocalOnly" (optional.String) - Vendor-specific query parameter for consumed local only. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly\". + * @param "VendSpecEtsiMecIsLocal" (optional.String) - Vendor-specific query parameter for is local. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal\". + * @param "VendSpecEtsiMecScopeOfLocality" (optional.String) - Vendor-specific query parameter for scope of locality. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality\". +@return []DiscoveredApis +*/ + +type ServicesApiServicesGETOpts struct { + VendSpecEtsiMecSerinstanceId optional.String + ApiName optional.Interface + ApiInvokerId optional.String + VendSpecEtsiMecSercategoryId optional.String + VendSpecEtsiMecConsumedLocalOnly optional.String + VendSpecEtsiMecIsLocal optional.String + VendSpecEtsiMecScopeOfLocality optional.String +} + +func (a *ServicesApiService) ServicesGET(ctx context.Context, localVarOptionals *ServicesApiServicesGETOpts) ([]DiscoveredApis, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []DiscoveredApis + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/allServiceAPIs" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if localVarOptionals != nil && localVarOptionals.VendSpecEtsiMecSerinstanceId.IsSet() { + localVarQueryParams.Add("vend-spec-etsi-mec-serinstance-id", parameterToString(localVarOptionals.VendSpecEtsiMecSerinstanceId.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.ApiName.IsSet() { + localVarQueryParams.Add("api-name", parameterToString(localVarOptionals.ApiName.Value(), "multi")) + } + if localVarOptionals != nil && localVarOptionals.ApiInvokerId.IsSet() { + localVarQueryParams.Add("api-invoker-id", parameterToString(localVarOptionals.ApiInvokerId.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.VendSpecEtsiMecSercategoryId.IsSet() { + localVarQueryParams.Add("vend-spec-etsi-mec-sercategory-id", parameterToString(localVarOptionals.VendSpecEtsiMecSercategoryId.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.VendSpecEtsiMecConsumedLocalOnly.IsSet() { + localVarQueryParams.Add("vend-spec-etsi-mec-consumed-local-only", parameterToString(localVarOptionals.VendSpecEtsiMecConsumedLocalOnly.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.VendSpecEtsiMecIsLocal.IsSet() { + localVarQueryParams.Add("vend-spec-etsi-mec-is-local", parameterToString(localVarOptionals.VendSpecEtsiMecIsLocal.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.VendSpecEtsiMecScopeOfLocality.IsSet() { + localVarQueryParams.Add("vend-spec-etsi-mec-scope-of-locality", parameterToString(localVarOptionals.VendSpecEtsiMecScopeOfLocality.Value(), "")) + } + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v []DiscoveredApis + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 414 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +AppServicesApiService get services +This method retrieves information about a list of mecService resources. This method is typically used in \"service availability query\" procedure + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param apfId Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. + +@return []ServiceApiDescription +*/ +func (a *ServicesApiService) AppServicesGET(ctx context.Context, apfId string) ([]ServiceApiDescription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []ServiceApiDescription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{apfId}/service-apis" + localVarPath = strings.Replace(localVarPath, "{"+"apfId"+"}", fmt.Sprintf("%v", apfId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v []ServiceApiDescription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +AppServicesApiService Publish a new API +Enables a service consumer to request to publish a new API at the CCF. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param body + - @param apfId Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. + +@return ServiceApiDescription +*/ +func (a *ServicesApiService) AppServicesPOST(ctx context.Context, body ServiceApiDescription, apfId string) (ServiceApiDescription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue ServiceApiDescription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{apfId}/service-apis" + localVarPath = strings.Replace(localVarPath, "{"+"apfId"+"}", fmt.Sprintf("%v", apfId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + // body params + localVarPostBody = &body + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 201 { + var v ServiceApiDescription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +AppServicesApiService +The HTTP DELETE method allows a service consumer to delete an existing \"Individual APF published API\" resource at the CCF + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param apfId Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. + - @param serviceApiId Represents a MEC service instance. +*/ +func (a *ServicesApiService) AppServicesServiceIdDELETE(ctx context.Context, apfId string, serviceApiId string) (*http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Delete") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{apfId}/service-apis/{serviceApiId}" + localVarPath = strings.Replace(localVarPath, "{"+"apfId"+"}", fmt.Sprintf("%v", apfId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"serviceApiId"+"}", fmt.Sprintf("%v", serviceApiId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHttpResponse, newErr + } + newErr.model = v + return localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHttpResponse, newErr + } + newErr.model = v + return localVarHttpResponse, newErr + } + return localVarHttpResponse, newErr + } + + return localVarHttpResponse, nil +} + +/* +ServicesApiService +The HTTP GET method allows a service consumer to retrieve an existing \"Individual APF published API\" resource at the CCF. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param apfId Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. + - @param serviceApiId Represents a MEC service instance. + +@return []ServiceApiDescription +*/ +func (a *ServicesApiService) AppServicesServiceIdGET(ctx context.Context, apfId string, serviceApiId string) ([]ServiceApiDescription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []ServiceApiDescription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{apfId}/service-apis/{serviceApiId}" + localVarPath = strings.Replace(localVarPath, "{"+"apfId"+"}", fmt.Sprintf("%v", apfId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"serviceApiId"+"}", fmt.Sprintf("%v", serviceApiId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v []ServiceApiDescription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +ServicesApiService +The HTTP PATCH method allows a service consumer to modify an existing \"Individual APF published API\" resource at the CCF. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param body + - @param apfId Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. + - @param serviceApiId Represents a MEC service instance. + +@return []ServiceApiDescription +*/ +func (a *ServicesApiService) AppServicesServiceIdPATCH(ctx context.Context, body ServiceApiDescriptionPatch, apfId string, serviceApiId string) ([]ServiceApiDescription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Patch") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []ServiceApiDescription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{apfId}/service-apis/{serviceApiId}" + localVarPath = strings.Replace(localVarPath, "{"+"apfId"+"}", fmt.Sprintf("%v", apfId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"serviceApiId"+"}", fmt.Sprintf("%v", serviceApiId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + // body params + localVarPostBody = &body + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v []ServiceApiDescription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 412 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +ServicesApiService +The HTTP PUT method allows a service consumer to update an existing \"Individual APF published API\" resource at the CCF. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param body + - @param apfId Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. + - @param serviceApiId Represents a MEC service instance. + +@return []ServiceApiDescription +*/ +func (a *ServicesApiService) AppServicesServiceIdPUT(ctx context.Context, body ServiceApiDescription, apfId string, serviceApiId string) ([]ServiceApiDescription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Put") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []ServiceApiDescription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{apfId}/service-apis/{serviceApiId}" + localVarPath = strings.Replace(localVarPath, "{"+"apfId"+"}", fmt.Sprintf("%v", apfId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"serviceApiId"+"}", fmt.Sprintf("%v", serviceApiId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + // body params + localVarPostBody = &body + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v []ServiceApiDescription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 412 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +AppSubscriptionsApiService Delete an existing CAPIF Event Subscription +This endpoint deletes an existing CAPIF Event Subscription resource. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param subscriberId This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). + - @param subscriptionId Represents a subscription to the notifications from the MEC platform. +*/ +func (a *ServicesApiService) ApplicationsSubscriptionDELETE(ctx context.Context, subscriberId string, subscriptionId string) (*http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Delete") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{subscriberId}/subscriptions/{subscriptionId} " + localVarPath = strings.Replace(localVarPath, "{"+"subscriberId"+"}", fmt.Sprintf("%v", subscriberId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"subscriptionId"+"}", fmt.Sprintf("%v", subscriptionId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + return localVarHttpResponse, newErr + } + + return localVarHttpResponse, nil +} + +/* +ServicesApiService Modify an existing CAPIF Event Subscription +This endpoint modifies an existing CAPIF Event Subscription resource. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param body + - @param subscriberId This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). + - @param subscriptionId Represents a subscription to the notifications from the MEC platform. + +@return EventSubscription +*/ +func (a *ServicesApiService) ApplicationsSubscriptionPatch(ctx context.Context, body EventSubscriptionPatch, subscriberId string, subscriptionId string) (EventSubscription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Patch") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue EventSubscription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{subscriberId}/subscriptions/{subscriptionId} " + localVarPath = strings.Replace(localVarPath, "{"+"subscriberId"+"}", fmt.Sprintf("%v", subscriberId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"subscriptionId"+"}", fmt.Sprintf("%v", subscriptionId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + // body params + localVarPostBody = &body + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v EventSubscription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +ServicesApiService Create a new CAPIF Events Subscription +Create a new CAPIF Events Subscription resource. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param body + - @param subscriberId This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). + +@return EventSubscription +*/ +func (a *ServicesApiService) ApplicationsSubscriptionsPOST(ctx context.Context, body EventSubscription, subscriberId string) (EventSubscription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue EventSubscription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{subscriberId}/subscriptions" + localVarPath = strings.Replace(localVarPath, "{"+"subscriberId"+"}", fmt.Sprintf("%v", subscriberId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + // body params + localVarPostBody = &body + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 201 { + var v EventSubscription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} + +/* +ServicesApiService The PUT method is used to update an existing subscription resource. +The susbcribing entity shall initiate the HTTP PUT request message and the CAPIF core function shall respond to the message. + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param body + - @param subscriberId This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). + - @param subscriptionId Represents a subscription to the notifications from the MEC platform. + +@return EventSubscription +*/ +func (a *ServicesApiService) ApplicationsSubscriptionsPUT(ctx context.Context, body EventSubscription, subscriberId string, subscriptionId string) (EventSubscription, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Put") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue EventSubscription + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/{subscriberId}/subscriptions/{subscriptionId} " + localVarPath = strings.Replace(localVarPath, "{"+"subscriberId"+"}", fmt.Sprintf("%v", subscriberId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"subscriptionId"+"}", fmt.Sprintf("%v", subscriptionId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHttpContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json", "application/problem+json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + // body params + localVarPostBody = &body + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v EventSubscription + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 400 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 403 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 404 { + var v ProblemDetails + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} diff --git a/go-packages/meep-capif-mgmt-client/client.go b/go-packages/meep-capif-mgmt-client/client.go new file mode 100644 index 000000000..433fea7da --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/client.go @@ -0,0 +1,478 @@ +/* + * 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 client + +import ( + "bytes" + "context" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" + "net/url" + "os" + "path/filepath" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + + "golang.org/x/oauth2" +) + +var ( + jsonCheck = regexp.MustCompile("(?i:[application|text]/json)") + xmlCheck = regexp.MustCompile("(?i:[application|text]/xml)") +) + +// APIClient manages communication with the MEC service management realized by CAPIF APIs API v3.2.1 +// In most cases there should be only one, shared, APIClient. +type APIClient struct { + cfg *Configuration + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // API Services + + // AppServicesApi *AppServicesApiService + + // AppSubscriptionsApi *AppSubscriptionsApiService + + ServicesApi *ServicesApiService +} + +type service struct { + client *APIClient +} + +// NewAPIClient creates a new API client. Requires a userAgent string describing your application. +// optionally a custom http.Client to allow for advanced features such as caching. +func NewAPIClient(cfg *Configuration) *APIClient { + if cfg.HTTPClient == nil { + cfg.HTTPClient = http.DefaultClient + } + + c := &APIClient{} + c.cfg = cfg + c.common.client = c + + // API Services + c.ServicesApi = (*ServicesApiService)(&c.common) + + return c +} + +func atoi(in string) (int, error) { + return strconv.Atoi(in) +} + +// selectHeaderContentType select a content type from the available list. +func selectHeaderContentType(contentTypes []string) string { + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] // use the first content type specified in 'consumes' +} + +// selectHeaderAccept join all accept types and return +func selectHeaderAccept(accepts []string) string { + if len(accepts) == 0 { + return "" + } + + if contains(accepts, "application/json") { + return "application/json" + } + + return strings.Join(accepts, ",") +} + +// contains is a case insenstive match, finding needle in a haystack +func contains(haystack []string, needle string) bool { + for _, a := range haystack { + if strings.ToLower(a) == strings.ToLower(needle) { + return true + } + } + return false +} + +// Verify optional parameters are of the correct type. +func typeCheckParameter(obj interface{}, expected string, name string) error { + // Make sure there is an object. + if obj == nil { + return nil + } + + // Check the type is as expected. + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String()) + } + return nil +} + +// parameterToString convert interface{} parameters to string, using a delimiter if format is provided. +func parameterToString(obj interface{}, collectionFormat string) string { + var delimiter string + + switch collectionFormat { + case "pipes": + delimiter = "|" + case "ssv": + delimiter = " " + case "tsv": + delimiter = "\t" + case "csv": + delimiter = "," + } + + if reflect.TypeOf(obj).Kind() == reflect.Slice { + return strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]") + } + + return fmt.Sprintf("%v", obj) +} + +// callAPI do the request. +func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { + return c.cfg.HTTPClient.Do(request) +} + +// Change base path to allow switching to mocks +func (c *APIClient) ChangeBasePath(path string) { + c.cfg.BasePath = path +} + +// prepareRequest build the request +func (c *APIClient) prepareRequest( + ctx context.Context, + path string, method string, + postBody interface{}, + headerParams map[string]string, + queryParams url.Values, + formParams url.Values, + fileName string, + fileBytes []byte) (localVarRequest *http.Request, err error) { + + var body *bytes.Buffer + + // Detect postBody type and post. + if postBody != nil { + contentType := headerParams["Content-Type"] + if contentType == "" { + contentType = detectContentType(postBody) + headerParams["Content-Type"] = contentType + } + + body, err = setBody(postBody, contentType) + if err != nil { + return nil, err + } + } + + // add form parameters and file if available. + if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(fileBytes) > 0 && fileName != "") { + if body != nil { + return nil, errors.New("Cannot specify postBody and multipart form at the same time.") + } + body = &bytes.Buffer{} + w := multipart.NewWriter(body) + + for k, v := range formParams { + for _, iv := range v { + if strings.HasPrefix(k, "@") { // file + err = addFile(w, k[1:], iv) + if err != nil { + return nil, err + } + } else { // form value + w.WriteField(k, iv) + } + } + } + if len(fileBytes) > 0 && fileName != "" { + w.Boundary() + //_, fileNm := filepath.Split(fileName) + part, err := w.CreateFormFile("file", filepath.Base(fileName)) + if err != nil { + return nil, err + } + _, err = part.Write(fileBytes) + if err != nil { + return nil, err + } + // Set the Boundary in the Content-Type + headerParams["Content-Type"] = w.FormDataContentType() + } + + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + w.Close() + } + + if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 { + if body != nil { + return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.") + } + body = &bytes.Buffer{} + body.WriteString(formParams.Encode()) + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, err + } + + // Adding Query Param + query := url.Query() + for k, v := range queryParams { + for _, iv := range v { + query.Add(k, iv) + } + } + + // Encode the parameters. + url.RawQuery = query.Encode() + + // Generate a new request + if body != nil { + localVarRequest, err = http.NewRequest(method, url.String(), body) + } else { + localVarRequest, err = http.NewRequest(method, url.String(), nil) + } + if err != nil { + return nil, err + } + + // add header parameters, if any + if len(headerParams) > 0 { + headers := http.Header{} + for h, v := range headerParams { + headers.Set(h, v) + } + localVarRequest.Header = headers + } + + // Override request host, if applicable + if c.cfg.Host != "" { + localVarRequest.Host = c.cfg.Host + } + + // Add the user agent to the request. + localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent) + + if ctx != nil { + // add context to the request + localVarRequest = localVarRequest.WithContext(ctx) + + // Walk through any authentication. + + // OAuth2 authentication + if tok, ok := ctx.Value(ContextOAuth2).(oauth2.TokenSource); ok { + // We were able to grab an oauth2 token from the context + var latestToken *oauth2.Token + if latestToken, err = tok.Token(); err != nil { + return nil, err + } + + latestToken.SetAuthHeader(localVarRequest) + } + + // Basic HTTP Authentication + if auth, ok := ctx.Value(ContextBasicAuth).(BasicAuth); ok { + localVarRequest.SetBasicAuth(auth.UserName, auth.Password) + } + + // AccessToken Authentication + if auth, ok := ctx.Value(ContextAccessToken).(string); ok { + localVarRequest.Header.Add("Authorization", "Bearer "+auth) + } + } + + for header, value := range c.cfg.DefaultHeader { + localVarRequest.Header.Add(header, value) + } + + return localVarRequest, nil +} + +func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { + if strings.Contains(contentType, "application/xml") { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } else if strings.Contains(contentType, "application/json") { + if err = json.Unmarshal(b, v); err != nil { + return err + } + return nil + } + return errors.New("undefined response type") +} + +// Add a file to the multipart request +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + part, err := w.CreateFormFile(fieldName, filepath.Base(path)) + if err != nil { + return err + } + _, err = io.Copy(part, file) + + return err +} + +// Prevent trying to import "fmt" +func reportError(format string, a ...interface{}) error { + return fmt.Errorf(format, a...) +} + +// Set request body from an interface{} +func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if jsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if xmlCheck.MatchString(contentType) { + xml.NewEncoder(bodyBuf).Encode(body) + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("Invalid body type %s\n", contentType) + return nil, err + } + return bodyBuf, nil +} + +// detectContentType method is used to figure out `Request.Body` content type for request header +func detectContentType(body interface{}) string { + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType +} + +// Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// CacheExpires helper function to determine remaining time before repeating a request. +func CacheExpires(r *http.Response) time.Time { + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } + expires = now.Add(lifetime) + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires +} + +func strlen(s string) int { + return utf8.RuneCountInString(s) +} + +// GenericSwaggerError Provides access to the body, error and model on returned errors. +type GenericSwaggerError struct { + body []byte + error string + model interface{} +} + +// Error returns non-empty string if there was an error. +func (e GenericSwaggerError) Error() string { + return e.error +} + +// Body returns the raw bytes of the response +func (e GenericSwaggerError) Body() []byte { + return e.body +} + +// Model returns the unpacked model of the error +func (e GenericSwaggerError) Model() interface{} { + return e.model +} diff --git a/go-packages/meep-capif-mgmt-client/configuration.go b/go-packages/meep-capif-mgmt-client/configuration.go new file mode 100644 index 000000000..e26abe3cc --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/configuration.go @@ -0,0 +1,72 @@ +/* + * 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 client + +import ( + "net/http" +) + +// contextKeys are used to identify the type of value in the context. +// Since these are string, it is possible to get a short description of the +// context key for logging and debugging using key.String(). + +type contextKey string + +func (c contextKey) String() string { + return "auth " + string(c) +} + +var ( + // ContextOAuth2 takes a oauth2.TokenSource as authentication for the request. + ContextOAuth2 = contextKey("token") + + // ContextBasicAuth takes BasicAuth as authentication for the request. + ContextBasicAuth = contextKey("basic") + + // ContextAccessToken takes a string oauth2 access token as authentication for the request. + ContextAccessToken = contextKey("accesstoken") + + // ContextAPIKey takes an APIKey as authentication for the request + ContextAPIKey = contextKey("apikey") +) + +// BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth +type BasicAuth struct { + UserName string `json:"userName,omitempty"` + Password string `json:"password,omitempty"` +} + +// APIKey provides API key based authentication to a request passed via context using ContextAPIKey +type APIKey struct { + Key string + Prefix string +} + +type Configuration struct { + BasePath string `json:"basePath,omitempty"` + Host string `json:"host,omitempty"` + Scheme string `json:"scheme,omitempty"` + DefaultHeader map[string]string `json:"defaultHeader,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + HTTPClient *http.Client +} + +func NewConfiguration() *Configuration { + cfg := &Configuration{ + BasePath: "https://localhost/sandboxname/service-apis/v1", + DefaultHeader: make(map[string]string), + UserAgent: "Swagger-Codegen/1.0.0/go", + } + return cfg +} + +func (c *Configuration) AddDefaultHeader(key string, value string) { + c.DefaultHeader[key] = value +} diff --git a/go-packages/meep-capif-mgmt-client/docs/AppServicesApi.md b/go-packages/meep-capif-mgmt-client/docs/AppServicesApi.md new file mode 100644 index 000000000..d18947c87 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/AppServicesApi.md @@ -0,0 +1,188 @@ +# {{classname}} + +All URIs are relative to *https://localhost/sandboxname/service-apis/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**AppServicesGET**](AppServicesApi.md#AppServicesGET) | **Get** /{apfId}/service-apis | get services +[**AppServicesPOST**](AppServicesApi.md#AppServicesPOST) | **Post** /{apfId}/service-apis | Publish a new API +[**AppServicesServiceIdDELETE**](AppServicesApi.md#AppServicesServiceIdDELETE) | **Delete** /{apfId}/service-apis/{serviceApiId} | +[**AppServicesServiceIdGET**](AppServicesApi.md#AppServicesServiceIdGET) | **Get** /{apfId}/service-apis/{serviceApiId} | +[**AppServicesServiceIdPATCH**](AppServicesApi.md#AppServicesServiceIdPATCH) | **Patch** /{apfId}/service-apis/{serviceApiId} | +[**AppServicesServiceIdPUT**](AppServicesApi.md#AppServicesServiceIdPUT) | **Put** /{apfId}/service-apis/{serviceApiId} | + +# **AppServicesGET** +> []ServiceApiDescription AppServicesGET(ctx, apfId) +get services + +This method retrieves information about a list of mecService resources. This method is typically used in \"service availability query\" procedure + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **apfId** | **string**| Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. | + +### Return type + +[**[]ServiceApiDescription**](ServiceAPIDescription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **AppServicesPOST** +> ServiceApiDescription AppServicesPOST(ctx, body, apfId) +Publish a new API + +Enables a service consumer to request to publish a new API at the CCF. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**ServiceApiDescription**](ServiceApiDescription.md)| | + **apfId** | **string**| Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. | + +### Return type + +[**ServiceApiDescription**](ServiceAPIDescription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **AppServicesServiceIdDELETE** +> AppServicesServiceIdDELETE(ctx, apfId, serviceApiId) + + +The HTTP DELETE method allows a service consumer to delete an existing \"Individual APF published API\" resource at the CCF + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **apfId** | **string**| Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. | + **serviceApiId** | **string**| Represents a MEC service instance. | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **AppServicesServiceIdGET** +> []ServiceApiDescription AppServicesServiceIdGET(ctx, apfId, serviceApiId) + + +The HTTP GET method allows a service consumer to retrieve an existing \"Individual APF published API\" resource at the CCF. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **apfId** | **string**| Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. | + **serviceApiId** | **string**| Represents a MEC service instance. | + +### Return type + +[**[]ServiceApiDescription**](ServiceAPIDescription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **AppServicesServiceIdPATCH** +> []ServiceApiDescription AppServicesServiceIdPATCH(ctx, body, apfId, serviceApiId) + + +The HTTP PATCH method allows a service consumer to modify an existing \"Individual APF published API\" resource at the CCF. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**ServiceApiDescriptionPatch**](ServiceApiDescriptionPatch.md)| | + **apfId** | **string**| Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. | + **serviceApiId** | **string**| Represents a MEC service instance. | + +### Return type + +[**[]ServiceApiDescription**](ServiceAPIDescription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **AppServicesServiceIdPUT** +> []ServiceApiDescription AppServicesServiceIdPUT(ctx, body, apfId, serviceApiId) + + +The HTTP PUT method allows a service consumer to update an existing \"Individual APF published API\" resource at the CCF. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**ServiceApiDescription**](ServiceApiDescription.md)| | + **apfId** | **string**| Identifier of the entity that registers the service API. If the MEC app plays the role of the APF, this variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the MEC platform plays the role of the APF, this variable shall be set to a specific identifier that identifies the MEC platform. | + **serviceApiId** | **string**| Represents a MEC service instance. | + +### Return type + +[**[]ServiceApiDescription**](ServiceAPIDescription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/AppSubscriptionsApi.md b/go-packages/meep-capif-mgmt-client/docs/AppSubscriptionsApi.md new file mode 100644 index 000000000..5e65776e1 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/AppSubscriptionsApi.md @@ -0,0 +1,129 @@ +# {{classname}} + +All URIs are relative to *https://localhost/sandboxname/service-apis/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**ApplicationsSubscriptionDELETE**](AppSubscriptionsApi.md#ApplicationsSubscriptionDELETE) | **Delete** /{subscriberId}/subscriptions/{subscriptionId} | Delete an existing CAPIF Event Subscription +[**ApplicationsSubscriptionPatch**](AppSubscriptionsApi.md#ApplicationsSubscriptionPatch) | **Patch** /{subscriberId}/subscriptions/{subscriptionId} | Modify an existing CAPIF Event Subscription +[**ApplicationsSubscriptionsPOST**](AppSubscriptionsApi.md#ApplicationsSubscriptionsPOST) | **Post** /{subscriberId}/subscriptions | Create a new CAPIF Events Subscription +[**ApplicationsSubscriptionsPUT**](AppSubscriptionsApi.md#ApplicationsSubscriptionsPUT) | **Put** /{subscriberId}/subscriptions/{subscriptionId} | The PUT method is used to update an existing subscription resource. + +# **ApplicationsSubscriptionDELETE** +> ApplicationsSubscriptionDELETE(ctx, subscriberId, subscriptionId) +Delete an existing CAPIF Event Subscription + +This endpoint deletes an existing CAPIF Event Subscription resource. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **subscriberId** | **string**| This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). | + **subscriptionId** | **string**| Represents a subscription to the notifications from the MEC platform. | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: Not defined + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **ApplicationsSubscriptionPatch** +> EventSubscription ApplicationsSubscriptionPatch(ctx, body, subscriberId, subscriptionId) +Modify an existing CAPIF Event Subscription + +This endpoint modifies an existing CAPIF Event Subscription resource. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**EventSubscriptionPatch**](EventSubscriptionPatch.md)| | + **subscriberId** | **string**| This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). | + **subscriptionId** | **string**| Represents a subscription to the notifications from the MEC platform. | + +### Return type + +[**EventSubscription**](EventSubscription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **ApplicationsSubscriptionsPOST** +> EventSubscription ApplicationsSubscriptionsPOST(ctx, body, subscriberId) +Create a new CAPIF Events Subscription + +Create a new CAPIF Events Subscription resource. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**EventSubscription**](EventSubscription.md)| | + **subscriberId** | **string**| This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). | + +### Return type + +[**EventSubscription**](EventSubscription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **ApplicationsSubscriptionsPUT** +> EventSubscription ApplicationsSubscriptionsPUT(ctx, body, subscriberId, subscriptionId) +The PUT method is used to update an existing subscription resource. + +The susbcribing entity shall initiate the HTTP PUT request message and the CAPIF core function shall respond to the message. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**EventSubscription**](EventSubscription.md)| | + **subscriberId** | **string**| This variable shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). | + **subscriptionId** | **string**| Represents a subscription to the notifications from the MEC platform. | + +### Return type + +[**EventSubscription**](EventSubscription.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/CapifEvent.md b/go-packages/meep-capif-mgmt-client/docs/CapifEvent.md new file mode 100644 index 000000000..9d899e981 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/CapifEvent.md @@ -0,0 +1,8 @@ +# CapifEvent + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/CategoryRef.md b/go-packages/meep-capif-mgmt-client/docs/CategoryRef.md new file mode 100644 index 000000000..0a6c18c2a --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/CategoryRef.md @@ -0,0 +1,12 @@ +# CategoryRef + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Href** | **string** | Reference of the catalogue | [default to null] +**Id** | **string** | Unique identifier of the category | [default to null] +**Name** | **string** | Name of the category, example values include RNI, Location & Bandwidth Management | [default to null] +**Version** | **string** | Category version | [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/DiscoveredApis.md b/go-packages/meep-capif-mgmt-client/docs/DiscoveredApis.md new file mode 100644 index 000000000..254b516a6 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/DiscoveredApis.md @@ -0,0 +1,9 @@ +# DiscoveredApis + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ServiceAPIDescriptions** | [**[]ServiceApiDescription**](ServiceAPIDescription.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/EventNotification.md b/go-packages/meep-capif-mgmt-client/docs/EventNotification.md new file mode 100644 index 000000000..53a620292 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/EventNotification.md @@ -0,0 +1,9 @@ +# EventNotification + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Events** | [**[]CapifEvent**](CAPIFEvent.md) | The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE, and SERVICE_API_UPDATE defined in the type \"CAPIFEvent\" shall be supported. The remaining values of that type need not be supported. | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/EventSubscription.md b/go-packages/meep-capif-mgmt-client/docs/EventSubscription.md new file mode 100644 index 000000000..a0bbcbec2 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/EventSubscription.md @@ -0,0 +1,12 @@ +# EventSubscription + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Events** | [**[]CapifEvent**](CAPIFEvent.md) | | [default to null] +**NotificationDestination** | **string** | URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response. | [default to null] +**RequestTestNotification** | **bool** | | [optional] [default to null] +**WebsocketNotifConfig** | **string** | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/EventSubscriptionPatch.md b/go-packages/meep-capif-mgmt-client/docs/EventSubscriptionPatch.md new file mode 100644 index 000000000..1a677d91b --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/EventSubscriptionPatch.md @@ -0,0 +1,10 @@ +# EventSubscriptionPatch + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Events** | [**[]CapifEvent**](CAPIFEvent.md) | The events for which the subscription is modified. | [default to null] +**NotificationDestination** | **string** | URI to which notifications will be sent. Shall be set to the value of the \"callbackReference\" attribute in the \"SerAvailabilityNotificationSubscription\" structure. | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/LocalityType.md b/go-packages/meep-capif-mgmt-client/docs/LocalityType.md new file mode 100644 index 000000000..ebfe404b7 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/LocalityType.md @@ -0,0 +1,8 @@ +# LocalityType + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExt.md b/go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExt.md new file mode 100644 index 000000000..12ba24425 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExt.md @@ -0,0 +1,14 @@ +# MecServiceInfoCapifExt + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Serializer** | [***SerializerType**](SerializerType.md) | | [optional] [default to null] +**State** | [***ServiceState**](ServiceState.md) | | [optional] [default to null] +**ScopeOfLocality** | [***LocalityType**](LocalityType.md) | | [optional] [default to null] +**ConsumedLocalOnly** | **bool** | | [optional] [default to null] +**IsLocal** | **bool** | | [optional] [default to null] +**Category** | [***CategoryRef**](CategoryRef.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExtPatch.md b/go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExtPatch.md new file mode 100644 index 000000000..f654c6ec1 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/MecServiceInfoCapifExtPatch.md @@ -0,0 +1,14 @@ +# MecServiceInfoCapifExtPatch + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Serializer** | [***SerializerType**](SerializerType.md) | | [optional] [default to null] +**State** | [***ServiceState**](ServiceState.md) | | [optional] [default to null] +**ScopeOfLocality** | [***LocalityType**](LocalityType.md) | | [optional] [default to null] +**ConsumedLocalOnly** | **bool** | | [optional] [default to null] +**IsLocal** | **bool** | | [optional] [default to null] +**Category** | [***CategoryRef**](CategoryRef.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/ProblemDetails.md b/go-packages/meep-capif-mgmt-client/docs/ProblemDetails.md new file mode 100644 index 000000000..8f884564e --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/ProblemDetails.md @@ -0,0 +1,13 @@ +# ProblemDetails + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Type_** | **string** | A URI reference according to IETF RFC 3986 that identifies the problem type | [optional] [default to null] +**Title** | **string** | A short, human-readable summary of the problem type | [optional] [default to null] +**Status** | **int32** | The HTTP status code for this occurrence of the problem | [default to null] +**Detail** | **string** | A human-readable explanation specific to this occurrence of the problem | [default to null] +**Instance** | **string** | A URI reference that identifies the specific occurrence of the problem | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/SerializerType.md b/go-packages/meep-capif-mgmt-client/docs/SerializerType.md new file mode 100644 index 000000000..210b39293 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/SerializerType.md @@ -0,0 +1,8 @@ +# SerializerType + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/ServiceApiDescription.md b/go-packages/meep-capif-mgmt-client/docs/ServiceApiDescription.md new file mode 100644 index 000000000..94d968cdb --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/ServiceApiDescription.md @@ -0,0 +1,11 @@ +# ServiceApiDescription + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ApiName** | **string** | Shall be set to the value of the \"serName\" attribute as defined in clause 8.1.2.2. | [optional] [default to null] +**ApiId** | **string** | If present, shall be set to the value of the \"serInstanceId\" attribute as defined in clause 8.1.2.2. | [optional] [default to null] +**VendorSpecificUrnetsimeccapifextserviceInfo** | [***MecServiceInfoCapifExt**](MecServiceInfoCapifExt.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/ServiceApiDescriptionPatch.md b/go-packages/meep-capif-mgmt-client/docs/ServiceApiDescriptionPatch.md new file mode 100644 index 000000000..43d6ce308 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/ServiceApiDescriptionPatch.md @@ -0,0 +1,9 @@ +# ServiceApiDescriptionPatch + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**VendorSpecificUrnetsimeccapifextserviceInfo** | [***MecServiceInfoCapifExtPatch**](MecServiceInfoCapifExtPatch.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/ServiceState.md b/go-packages/meep-capif-mgmt-client/docs/ServiceState.md new file mode 100644 index 000000000..b6b4bfc9e --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/ServiceState.md @@ -0,0 +1,8 @@ +# ServiceState + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/docs/ServicesApi.md b/go-packages/meep-capif-mgmt-client/docs/ServicesApi.md new file mode 100644 index 000000000..81f3b272c --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/docs/ServicesApi.md @@ -0,0 +1,48 @@ +# {{classname}} + +All URIs are relative to *https://localhost/sandboxname/service-apis/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**ServicesGET**](ServicesApi.md#ServicesGET) | **Get** /allServiceAPIs | + +# **ServicesGET** +> []DiscoveredApis ServicesGET(ctx, optional) + + +This method retrieves information about a list of mecService resources. This method is typically used in \"service availability query\" procedure + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **optional** | ***ServicesApiServicesGETOpts** | optional parameters | nil if no parameters + +### Optional Parameters +Optional parameters are passed through a pointer to a ServicesApiServicesGETOpts struct +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **vendSpecEtsiMecSerinstanceId** | **optional.String**| Vendor-specific query parameter for service instance ID. The \"target\" attribute shall be set to \"/apiId\". | + **apiName** | [**optional.Interface of []string**](string.md)| This query parameter corresponds to the parameter \"ser_name\" as defined in clause 8.2.3.3.1. As opposed to the cardinality of ser_instance_id defined in clause 8.2.3.3.1 that is 0..N, this parameter only supports a cardinality of 0..1. | + **apiInvokerId** | **optional.String**| If the Discover_Service_API is produced by the MEC platform towards the MEC applications, this identifier shall be set to the value of the \"appInstanceId\" (see clause 7.1.2.6). If the Discover_Service_API is produced by the CCF, the provisions in clause 8.1.2.2.3.1 of 3GPP TS 29.222 [21] apply. | + **vendSpecEtsiMecSercategoryId** | **optional.String**| Vendor-specific query parameter for service category ID. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/serCategory/id\". | + **vendSpecEtsiMecConsumedLocalOnly** | **optional.String**| Vendor-specific query parameter for consumed local only. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/consumedLocalOnly\". | + **vendSpecEtsiMecIsLocal** | **optional.String**| Vendor-specific query parameter for is local. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/isLocal\". | + **vendSpecEtsiMecScopeOfLocality** | **optional.String**| Vendor-specific query parameter for scope of locality. The \"target\" attribute shall be set to \"/vendorSpecific-urn:etsi:mec:capifext:service-info/scopeOfLocality\". | + +### Return type + +[**[]DiscoveredApis**](DiscoveredAPIs.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json, application/problem+json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/go-packages/meep-capif-mgmt-client/git_push.sh b/go-packages/meep-capif-mgmt-client/git_push.sh new file mode 100644 index 000000000..ae01b182a --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/git_push.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/go-packages/meep-capif-mgmt-client/model_capif_event.go b/go-packages/meep-capif-mgmt-client/model_capif_event.go new file mode 100644 index 000000000..b7c8f2fe0 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_capif_event.go @@ -0,0 +1,20 @@ +/* + * 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 client + +// CapifEvent : The CAPIFEvent data type represents the type of events for which the subscription is made. +type CapifEvent string + +// List of CAPIFEvent +const ( + AVAILABLE_CapifEvent CapifEvent = "SERVICE_API_AVAILABLE" + UNAVAILABLE_CapifEvent CapifEvent = "SERVICE_API_UNAVAILABLE" + UPDATE_CapifEvent CapifEvent = "SERVICE_API_UPDATE" +) diff --git a/go-packages/meep-capif-mgmt-client/model_category_ref.go b/go-packages/meep-capif-mgmt-client/model_category_ref.go new file mode 100644 index 000000000..714b3eadb --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_category_ref.go @@ -0,0 +1,22 @@ +/* + * 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 client + +// This type represents the category reference +type CategoryRef struct { + // Reference of the catalogue + Href string `json:"href"` + // Unique identifier of the category + Id string `json:"id"` + // Name of the category, example values include RNI, Location & Bandwidth Management + Name string `json:"name"` + // Category version + Version string `json:"version"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_discovered_apis.go b/go-packages/meep-capif-mgmt-client/model_discovered_apis.go new file mode 100644 index 000000000..2c82e4f6e --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_discovered_apis.go @@ -0,0 +1,14 @@ +/* + * 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 client + +type DiscoveredApis struct { + ServiceAPIDescriptions []ServiceApiDescription `json:"serviceAPIDescriptions,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_event_notification.go b/go-packages/meep-capif-mgmt-client/model_event_notification.go new file mode 100644 index 000000000..0be05ab97 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_event_notification.go @@ -0,0 +1,15 @@ +/* + * 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 client + +type EventNotification struct { + // The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE, and SERVICE_API_UPDATE defined in the type \"CAPIFEvent\" shall be supported. The remaining values of that type need not be supported. + Events []CapifEvent `json:"events,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_event_subscription.go b/go-packages/meep-capif-mgmt-client/model_event_subscription.go new file mode 100644 index 000000000..2d52e5518 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_event_subscription.go @@ -0,0 +1,18 @@ +/* + * 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 client + +type EventSubscription struct { + Events []CapifEvent `json:"events"` + // URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response. + NotificationDestination string `json:"notificationDestination"` + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + WebsocketNotifConfig string `json:"websocketNotifConfig,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_event_subscription_patch.go b/go-packages/meep-capif-mgmt-client/model_event_subscription_patch.go new file mode 100644 index 000000000..8c1c1a7d2 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_event_subscription_patch.go @@ -0,0 +1,17 @@ +/* + * 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 client + +type EventSubscriptionPatch struct { + // The events for which the subscription is modified. + Events []CapifEvent `json:"events"` + // URI to which notifications will be sent. Shall be set to the value of the \"callbackReference\" attribute in the \"SerAvailabilityNotificationSubscription\" structure. + NotificationDestination string `json:"notificationDestination,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_locality_type.go b/go-packages/meep-capif-mgmt-client/model_locality_type.go new file mode 100644 index 000000000..3a489388d --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_locality_type.go @@ -0,0 +1,23 @@ +/* + * 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 client + +// LocalityType : The enumeration LocalityType represents types of locality. +type LocalityType string + +// List of LocalityType +const ( + MEC_SYSTEM_LocalityType LocalityType = "MEC_SYSTEM" + MEC_HOST_LocalityType LocalityType = "MEC_HOST" + NFVI_POP_LocalityType LocalityType = "NFVI_POP" + ZONE_LocalityType LocalityType = "ZONE" + ZONE_GROUP_LocalityType LocalityType = "ZONE_GROUP" + NFVI_NODE_LocalityType LocalityType = "NFVI_NODE" +) diff --git a/go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext.go b/go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext.go new file mode 100644 index 000000000..9742e8aa6 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext.go @@ -0,0 +1,19 @@ +/* + * 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 client + +type MecServiceInfoCapifExt 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"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext_patch.go b/go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext_patch.go new file mode 100644 index 000000000..18aef795e --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_mec_service_info_capif_ext_patch.go @@ -0,0 +1,19 @@ +/* + * 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 client + +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"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_problem_details.go b/go-packages/meep-capif-mgmt-client/model_problem_details.go new file mode 100644 index 000000000..4adc74d7f --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_problem_details.go @@ -0,0 +1,23 @@ +/* + * 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 client + +type ProblemDetails struct { + // A URI reference according to IETF RFC 3986 that identifies the problem type + Type_ string `json:"type,omitempty"` + // A short, human-readable summary of the problem type + Title string `json:"title,omitempty"` + // The HTTP status code for this occurrence of the problem + Status int32 `json:"status"` + // A human-readable explanation specific to this occurrence of the problem + Detail string `json:"detail"` + // A URI reference that identifies the specific occurrence of the problem + Instance string `json:"instance,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_serializer_type.go b/go-packages/meep-capif-mgmt-client/model_serializer_type.go new file mode 100644 index 000000000..6c19ab084 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_serializer_type.go @@ -0,0 +1,20 @@ +/* + * 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 client + +// SerializerType : The enumeration SerializerType represents types of serializers. This enumeration shall be extensible. +type SerializerType string + +// List of SerializerType +const ( + JSON_SerializerType SerializerType = "JSON" + XML_SerializerType SerializerType = "XML" + PROTOBUF3_SerializerType SerializerType = "PROTOBUF3" +) diff --git a/go-packages/meep-capif-mgmt-client/model_service_api_description.go b/go-packages/meep-capif-mgmt-client/model_service_api_description.go new file mode 100644 index 000000000..f201cdb55 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_service_api_description.go @@ -0,0 +1,18 @@ +/* + * 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 client + +type ServiceApiDescription struct { + // Shall be set to the value of the \"serName\" attribute as defined in clause 8.1.2.2. + ApiName string `json:"apiName,omitempty"` + // If present, shall be set to the value of the \"serInstanceId\" attribute as defined in clause 8.1.2.2. + ApiId string `json:"apiId,omitempty"` + VendorSpecificUrnetsimeccapifextserviceInfo *MecServiceInfoCapifExt `json:"vendorSpecific-urn:etsi:mec:capifext:service-info,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_service_api_description_patch.go b/go-packages/meep-capif-mgmt-client/model_service_api_description_patch.go new file mode 100644 index 000000000..7c039f30e --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_service_api_description_patch.go @@ -0,0 +1,14 @@ +/* + * 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 client + +type ServiceApiDescriptionPatch struct { + VendorSpecificUrnetsimeccapifextserviceInfo *MecServiceInfoCapifExtPatch `json:"vendorSpecific-urn:etsi:mec:capifext:service-info,omitempty"` +} diff --git a/go-packages/meep-capif-mgmt-client/model_service_state.go b/go-packages/meep-capif-mgmt-client/model_service_state.go new file mode 100644 index 000000000..26f78ae42 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/model_service_state.go @@ -0,0 +1,20 @@ +/* + * 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 client + +// ServiceState : The enumeration ServiceState represents possible states of a MEC service instance. +type ServiceState string + +// List of ServiceState +const ( + ACTIVE_ServiceState ServiceState = "ACTIVE" + INACTIVE_ServiceState ServiceState = "INACTIVE" + SUSPENDED_ServiceState ServiceState = "SUSPENDED" +) diff --git a/go-packages/meep-capif-mgmt-client/response.go b/go-packages/meep-capif-mgmt-client/response.go new file mode 100644 index 000000000..9f0b81d63 --- /dev/null +++ b/go-packages/meep-capif-mgmt-client/response.go @@ -0,0 +1,43 @@ +/* + * 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 client + +import ( + "net/http" +) + +type APIResponse struct { + *http.Response `json:"-"` + Message string `json:"message,omitempty"` + // Operation is the name of the swagger operation. + Operation string `json:"operation,omitempty"` + // RequestURL is the request URL. This value is always available, even if the + // embedded *http.Response is nil. + RequestURL string `json:"url,omitempty"` + // Method is the HTTP method used for the request. This value is always + // available, even if the embedded *http.Response is nil. + Method string `json:"method,omitempty"` + // Payload holds the contents of the response body (which may be nil or empty). + // This is provided here as the raw response.Body() reader will have already + // been drained. + Payload []byte `json:"-"` +} + +func NewAPIResponse(r *http.Response) *APIResponse { + + response := &APIResponse{Response: r} + return response +} + +func NewAPIResponseWithError(errorMessage string) *APIResponse { + + response := &APIResponse{Message: errorMessage} + return response +} -- GitLab From 5419019bf9c0e56495830557679417e61daedfd9 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Mon, 5 Aug 2024 11:02:43 +0500 Subject: [PATCH 02/43] Update router file as per Resource: APF published APIs --- go-apps/meep-app-enablement/server/routers.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 88a68f97a..04a33c62d 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -334,6 +334,18 @@ var routes = Routes{ "/service-apis/v1/allServiceAPIs", capifMgmt.ServicesGET, }, + Route{ + "AppServicesGET", + strings.ToUpper("Get"), + "/published-apis/v1//{apfId}/service-apis", + capifMgmt.AppServicesGET, + }, + Route{ + "AppServicesPOST", + strings.ToUpper("Post"), + "/published-apis/v1//{apfId}/service-apis", + capifMgmt.AppServicesPOST, + }, Route{ "Index", "GET", -- GitLab From b74d9858cf3a16870cfada271fb9940358883f5a Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Mon, 5 Aug 2024 11:23:03 +0500 Subject: [PATCH 03/43] Fix minor issue in router.go file --- go-apps/meep-app-enablement/server/routers.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 04a33c62d..d479dc18b 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -337,13 +337,13 @@ var routes = Routes{ Route{ "AppServicesGET", strings.ToUpper("Get"), - "/published-apis/v1//{apfId}/service-apis", + "/published-apis/v1/{apfId}/service-apis", capifMgmt.AppServicesGET, }, Route{ "AppServicesPOST", strings.ToUpper("Post"), - "/published-apis/v1//{apfId}/service-apis", + "/published-apis/v1/{apfId}/service-apis", capifMgmt.AppServicesPOST, }, Route{ -- GitLab From 8bbf12234d4229eadb8effd9a79e99ff13b2df0b Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 7 Aug 2024 07:09:36 +0000 Subject: [PATCH 04/43] Fix issue related handle request from multiple server(different URL's) --- charts/meep-app-enablement/values-template.yaml | 8 ++++++++ .../server/capif-mgmt/service-mgmt.go | 2 +- go-apps/meep-app-enablement/server/routers.go | 11 +++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/charts/meep-app-enablement/values-template.yaml b/charts/meep-app-enablement/values-template.yaml index 1f08fae83..e9b2391e9 100644 --- a/charts/meep-app-enablement/values-template.yaml +++ b/charts/meep-app-enablement/values-template.yaml @@ -46,9 +46,13 @@ ingress: {{- if .IsMepService }} - /{{.SandboxName}}/{{.MepName}}/mec_app_support - /{{.SandboxName}}/{{.MepName}}/mec_service_mgmt + - /{{.SandboxName}}/{{.MepName}}/service-apis + - /{{.SandboxName}}/{{.MepName}}/published-apis {{- else }} - /{{.SandboxName}}/mec_app_support - /{{.SandboxName}}/mec_service_mgmt + - /{{.SandboxName}}/service-apis + - /{{.SandboxName}}/published-apis {{- end }} annotations: kubernetes.io/ingress.class: nginx @@ -57,10 +61,14 @@ ingress: nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^/{{ .SandboxName }}/{{.MepName}}/mec_app_support(/|$)(.*)$ /mec_app_support/$2 break; rewrite ^/{{ .SandboxName }}/{{.MepName}}/mec_service_mgmt(/|$)(.*)$ /mec_service_mgmt/$2 break; + rewrite ^/{{ .SandboxName }}/{{.MepName}}/service-apis(/|$)(.*)$ /service-apis/$2 break; + rewrite ^/{{ .SandboxName }}/{{.MepName}}/published-apis(/|$)(.*)$ /published-apis/$2 break; {{- else }} nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^/{{ .SandboxName }}/mec_app_support(/|$)(.*)$ /mec_app_support/$2 break; rewrite ^/{{ .SandboxName }}/mec_service_mgmt(/|$)(.*)$ /mec_service_mgmt/$2 break; + rewrite ^/{{ .SandboxName }}/service-apis(/|$)(.*)$ /service-apis/$2 break; + rewrite ^/{{ .SandboxName }}/published-apis(/|$)(.*)$ /published-apis/$2 break; {{- end }} {{- if .AuthEnabled }} nginx.ingress.kubernetes.io/auth-url: https://$http_host/auth/v1/authenticate?svc=meep-app-enablement&sbox={{.SandboxName}}&mep={{.MepName}} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index e307f92b5..fd7bf8e4d 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -537,7 +537,7 @@ func appServicesGET(w http.ResponseWriter, r *http.Request) { log.Info("appServicesGET") w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) - appId := vars["appInstanceId"] + appId := vars["apfId"] mutex.Lock() defer mutex.Unlock() diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index d479dc18b..bfc34c6ac 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -328,24 +328,35 @@ var routes = Routes{ "/service-apis/v1/", Index, }, + Route{ "ServicesGET", strings.ToUpper("Get"), "/service-apis/v1/allServiceAPIs", capifMgmt.ServicesGET, }, + + Route{ + "Index", + "GET", + "/published-apis/v1/", + Index, + }, + Route{ "AppServicesGET", strings.ToUpper("Get"), "/published-apis/v1/{apfId}/service-apis", capifMgmt.AppServicesGET, }, + Route{ "AppServicesPOST", strings.ToUpper("Post"), "/published-apis/v1/{apfId}/service-apis", capifMgmt.AppServicesPOST, }, + Route{ "Index", "GET", -- GitLab From 6c1168bd3a0c1123b0c2f90b0251e23f86c24664 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 9 Aug 2024 14:40:10 +0500 Subject: [PATCH 05/43] Add aef_profile data model for serv-mgmt --- .../api/capif-mgmt/swagger.yaml | 188 ++++++++++++++++++ .../server/capif-mgmt/model_aef_profile.go | 21 ++ .../model_mec_transport_info_capif_ext.go | 29 +++ .../model_service_api_description.go | 3 +- .../server/capif-mgmt/service-mgmt.go | 17 +- 5 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_aef_profile.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_mec_transport_info_capif_ext.go diff --git a/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml b/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml index a08ba68fc..e803dcdbe 100644 --- a/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml +++ b/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml @@ -1131,6 +1131,11 @@ components: type: string description: | If present, shall be set to the value of the "serInstanceId" attribute as defined in clause 8.1.2.2. + aefProfiles: + type: array + items: + $ref: '#/components/schemas/AefProfile' + description: "AEF profile information, which includes the exposed API details (e.g., protocol). For CAPIF-4/4e interface, API publishing function shall provide this attribute to the CCF in service API publishing. For CAPIF-1/1e interface, the CCF shall provide this attribute to the API Invoker during service API discovery." vendorSpecific-urn:etsi:mec:capifext:service-info: $ref: '#/components/schemas/MecServiceInfoCapifExt' example: @@ -1162,6 +1167,7 @@ components: type: boolean category: $ref: '#/components/schemas/CategoryRef' + MecServiceInfoCapifExt: type: object properties: @@ -1188,6 +1194,188 @@ components: id: id version: version isLocal: true + AefProfile: + type: object + properties: + aefId: + type: string + description: "AEF identifier. Shall be set to the value of the 'id' attribute as defined in clause 8.1.2.3." + versions: + type: array + items: + type: string + description: "API version. This array shall contain a single entry." + minItems: 1 + maxItems: 1 + interfaceDescriptions: + description: This type represents information about a transport endpoint + oneOf: + - $ref: '#/components/schemas/EndPointInfo.Uris' + - $ref: '#/components/schemas/EndPointInfo.Fqdn' + - $ref: '#/components/schemas/EndPointInfo.Addresses' + - $ref: '#/components/schemas/EndPointInfo.Alternative' + x-etsi-notes: "NOTE:\tExactly one of \"uris\", \"fqdn\", \"addresses\" or\ + \ \"alternative\" shall be present." + vendorSpecific-urn:etsi:mec:capifext:transport-info : + $ref: '#/components/schemas/MecTransportInfoCapifExt' + description: "Additional attribute of data type MecTransportInfoCapifExt for MEC-specific CAPIF extensions related to alternative transports." + required: + - aefId + - versions + MecTransportInfoCapifExt: + type: object + properties: + name: + type: string + description: "Name of the transport info." + description: + type: string + description: "Description of the transport info." + type: + $ref: '#/components/schemas/TransportType' + protocol: + type: string + description: The name of the protocol used. Shall be set to HTTP for a REST + API. + example: "[\"HTTP\"]" + version: + type: string + description: The version of the protocol used + example: "[\"2.0\"]" + security: + $ref: '#/components/schemas/SecurityInfo' + description: "Security information of the transport." + implSpecificInfo: + type: string + description: Additional implementation specific details of the transport + description: This type represents the general information of a MEC service. + SecurityInfo.OAuth2Info.GrantType: + title: SecurityInfo.OAuth2Info.GrantType + type: string + description: OAuth 2.0 grant type + example: "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + enum: + - OAUTH2_AUTHORIZATION_CODE + - OAUTH2_IMPLICIT_GRANT + - OAUTH2_RESOURCE_OWNER + - OAUTH2_CLIENT_CREDENTIALS + SecurityInfo.OAuth2Info: + title: SecurityInfo.OAuth2Info + required: + - grantTypes + - tokenEndpoint + type: object + properties: + grantTypes: + maxItems: 4 + minItems: 1 + type: array + description: List of supported OAuth 2.0 grant types. + items: + $ref: '#/components/schemas/SecurityInfo.OAuth2Info.GrantType' + tokenEndpoint: + type: string + description: The token endpoint + example: "[\"/mecSerMgmtApi/security/TokenEndPoint\"]" + description: Parameters related to use of OAuth 2.0 + example: + tokenEndpoint: "[\"/mecSerMgmtApi/security/TokenEndPoint\"]" + grantTypes: + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + SecurityInfo: + title: SecurityInfo + type: object + properties: + oAuth2Info: + $ref: '#/components/schemas/SecurityInfo.OAuth2Info' + description: This type represents security information related to a transport + example: + oAuth2Info: + tokenEndpoint: "[\"/mecSerMgmtApi/security/TokenEndPoint\"]" + grantTypes: + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + - "[\"OAUTH2_CLIENT_CREDENTIALS\"]" + TransportType: + title: TransportType + type: string + description: The enumeration TransportType represents types of transports + example: "[\"REST_HTTP\"]" + enum: + - REST_HTTP + - MB_TOPIC_BASED + - MB_ROUTING + - MB_PUBSUB + - RPC + - RPC_STREAMING + - WEBSOCKET + EndPointInfo.Alternative: + title: EndPointInfo.Alternative + required: + - alternative + type: object + properties: + alternative: + type: object + description: "Entry point information of the service in a format defined\ + \ by an implementation, or in an external specification. See note." + description: This type represents information about a transport endpoint. + EndPointInfo.Address: + title: EndPointInfo.Address + required: + - host + - port + type: object + properties: + host: + type: string + description: Host portion of the address + example: "[\"192.0.2.0\"]" + port: + type: integer + description: Port portion of the address + description: A IP address and port pair + EndPointInfo.Addresses: + title: EndPointInfo.Addresses + required: + - addresses + type: object + properties: + addresses: + type: array + description: Entry point information of the service as one or more pairs + of IP address and port. See note. + items: + $ref: '#/components/schemas/EndPointInfo.Address' + EndPointInfo.Fqdn: + title: EndPointInfo.Fqdn + required: + - fqdn + type: object + properties: + fqdn: + type: array + description: Fully Qualified Domain Name of the service. See note. + items: + type: string + description: 'This type represents information about a transport endpoint. ' + EndPointInfo.Uris: + title: EndPointInfo.Uris + required: + - uris + type: object + properties: + uris: + type: array + description: "Entry point information of the service as string, formatted\ + \ according to URI syntax" + items: + type: string + description: This type represents information about a transport endpoint. responses: "400": description: Bad Request. It is used to indicate that incorrect parameters were diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_aef_profile.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_aef_profile.go new file mode 100644 index 000000000..a75f72a07 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_aef_profile.go @@ -0,0 +1,21 @@ +/* + * 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 AefProfile struct { + // AEF identifier. Shall be set to the value of the 'id' attribute as defined in clause 8.1.2.3. + AefId string `json:"aefId"` + + Versions []string `json:"versions"` + // This type represents information about a transport endpoint + InterfaceDescriptions *OneOfTransportInfoEndpoint `json:"interfaceDescriptions,omitempty"` + + VendorSpecificUrnetsimeccapifexttransportInfo *MecTransportInfoCapifExt `json:"vendorSpecific-urn:etsi:mec:capifext:transport-info,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_transport_info_capif_ext.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_transport_info_capif_ext.go new file mode 100644 index 000000000..b0adc7bfc --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_transport_info_capif_ext.go @@ -0,0 +1,29 @@ +/* + * 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 + +// This type represents the general information of a MEC service. + type MecTransportInfoCapifExt struct { + // Name of the transport info. + Name string `json:"name,omitempty"` + // Description of the transport info. + Description string `json:"description,omitempty"` + + Type_ *TransportType `json:"type,omitempty"` + // The name of the protocol used. Shall be set to HTTP for a REST API. + Protocol string `json:"protocol,omitempty"` + // The version of the protocol used + Version string `json:"version,omitempty"` + + Security *SecurityInfo `json:"security,omitempty"` + // Additional implementation specific details of the transport + ImplSpecificInfo string `json:"implSpecificInfo,omitempty"` + } + \ No newline at end of file diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go index 6ad3723ef..840c7f260 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description.go @@ -14,6 +14,7 @@ type ServiceApiDescription struct { ApiName string `json:"apiName,omitempty"` // If present, shall be set to the value of the \"serInstanceId\" attribute as defined in clause 8.1.2.2. ApiId string `json:"apiId,omitempty"` - + // AEF profile information, which includes the exposed API details (e.g., protocol). For CAPIF-4/4e interface, API publishing function shall provide this attribute to the CCF in service API publishing. For CAPIF-1/1e interface, the CCF shall provide this attribute to the API Invoker during service API discovery. + AefProfiles []AefProfile `json:"aefProfiles,omitempty"` VendorSpecificUrnetsimeccapifextserviceInfo *MecServiceInfoCapifExt `json:"vendorSpecific-urn:etsi:mec:capifext:service-info,omitempty"` } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index fd7bf8e4d..740820d99 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1318,9 +1318,22 @@ func getServices(w http.ResponseWriter, r *http.Request, appId string) { // Map ServiceInfoList to ServiceApiDescription list serviceApiDescriptions := make([]ServiceApiDescription, 0) for _, service := range sInfoList.Services { + aefProfile := AefProfile{ + AefId: service.TransportInfo.Id, + Versions: []string{service.Version}, // Assuming service.Version is a string, wrap it in a slice + InterfaceDescriptions: service.TransportInfo.Endpoint, + VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ + Name: service.TransportInfo.Name, + Type_: service.TransportInfo.Type_, + Protocol: service.TransportInfo.Protocol, + Version: service.TransportInfo.Version, + Security: service.TransportInfo.Security, + }, + } apiDesc := ServiceApiDescription{ - ApiName: service.SerName, - ApiId: service.SerInstanceId, + ApiName: service.SerName, + ApiId: service.SerInstanceId, + AefProfiles: []AefProfile{aefProfile}, VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ Serializer: service.Serializer, State: service.State, -- GitLab From 011d205f8d467238f01a69e54c53b47ca03c8613 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 9 Aug 2024 15:23:35 +0500 Subject: [PATCH 06/43] Add api-invoker-id query parameter functionality --- .../server/capif-mgmt/service-mgmt.go | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 740820d99..a58d17568 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -616,8 +616,23 @@ func servicesGET(w http.ResponseWriter, r *http.Request) { mutex.Lock() defer mutex.Unlock() + // Validate query parameters + u, _ := url.Parse(r.URL.String()) + q := u.Query() + validParams := []string{"api-invoker-id"} + err := validateQueryParams(q, validParams) + if err != nil { + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } - getServices(w, r, "") + // Extract and parse query parameters + api_invoker_id := q.Get("api-invoker-id") + if api_invoker_id != "" { + getServices(w, r, api_invoker_id) + } else { + getServices(w, r, "") + } } func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { @@ -1192,7 +1207,7 @@ func getServices(w http.ResponseWriter, r *http.Request, appId string) { // Validate query parameters u, _ := url.Parse(r.URL.String()) q := u.Query() - validParams := []string{"vend-spec-etsi-mec-serinstance-id", "api-name", "vend-spec-etsi-mec-sercategory-id", "vend-spec-etsi-mec-consumed-local-only", "vend-spec-etsi-mec-is-local", "vend-spec-etsi-mec-scope-of-locality"} + validParams := []string{"api-invoker-id", "vend-spec-etsi-mec-serinstance-id", "api-name", "vend-spec-etsi-mec-sercategory-id", "vend-spec-etsi-mec-consumed-local-only", "vend-spec-etsi-mec-is-local", "vend-spec-etsi-mec-scope-of-locality"} err := validateQueryParams(q, validParams) if err != nil { errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) @@ -1320,7 +1335,7 @@ func getServices(w http.ResponseWriter, r *http.Request, appId string) { for _, service := range sInfoList.Services { aefProfile := AefProfile{ AefId: service.TransportInfo.Id, - Versions: []string{service.Version}, // Assuming service.Version is a string, wrap it in a slice + Versions: []string{service.Version}, InterfaceDescriptions: service.TransportInfo.Endpoint, VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ Name: service.TransportInfo.Name, -- GitLab From 5f404ae1117364c0db10b306f377e2d9622a12a7 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 13 Aug 2024 09:48:55 +0500 Subject: [PATCH 07/43] Implemet logic to create a service via CAPIF --- .../server/capif-mgmt/service-mgmt.go | 126 ++++++++++++------ 1 file changed, 86 insertions(+), 40 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index a58d17568..20271422f 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -214,7 +214,7 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) - appId := vars["appInstanceId"] + appId := vars["apfId"] mutex.Lock() defer mutex.Unlock() @@ -247,10 +247,15 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { } // NOTE: Set default values for omitted fields locality := MEC_HOST_LocalityType - sInfoPost := ServiceInfo{ - ScopeOfLocality: &locality, - IsLocal: true, - ConsumedLocalOnly: true, + sInfoPost := ServiceApiDescription{ + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + ScopeOfLocality: &locality, + IsLocal: true, + ConsumedLocalOnly: true, + }, + // ScopeOfLocality: &locality, + // IsLocal: true, + // ConsumedLocalOnly: true, } decoder := json.NewDecoder(r.Body) err = decoder.Decode(&sInfoPost) @@ -261,85 +266,126 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { } // Check for mandatory properties - if sInfoPost.SerInstanceId != "" { + if sInfoPost.ApiId != "" { errStr := "Service instance ID must not be present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.SerName == "" { + if sInfoPost.ApiName == "" { errStr := "Mandatory Service Name parameter not present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.Version == "" { + if len(sInfoPost.AefProfiles) == 0 || len(sInfoPost.AefProfiles[0].Versions) == 0 { errStr := "Mandatory Service Version parameter not present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.State == nil { + if sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.State == nil { errStr := "Mandatory Service State parameter not present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.Serializer == nil { + if sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer == nil { errStr := "Mandatory Serializer parameter not present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.SerCategory != nil { - errStr := validateCategoryRef(sInfoPost.SerCategory) + if sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.Category != nil { + errStr := validateCategoryRef(sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.Category) if errStr != "" { log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } } - if (sInfoPost.TransportId != "" && sInfoPost.TransportInfo != nil) || - (sInfoPost.TransportId == "" && sInfoPost.TransportInfo == nil) { - errStr := "Either transportId or transportInfo but not both shall be present" + + if len(sInfoPost.AefProfiles) == 0 || sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo == nil { + errStr := "Mandatory TransportInfo (VendorSpecificUrnetsimeccapifexttransportInfo) not present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.Links != nil { - errStr := "Links parameter should not be present in request" + if len(sInfoPost.AefProfiles) == 0 || sInfoPost.AefProfiles[0].InterfaceDescriptions == nil { + errStr := "Mandatory AefProfiles (InterfaceDescriptions) not present" log.Error(errStr) errHandlerProblemDetails(w, errStr, http.StatusBadRequest) return } - if sInfoPost.TransportInfo != nil { - if sInfoPost.TransportInfo.Id == "" || - sInfoPost.TransportInfo.Name == "" || - string(*sInfoPost.TransportInfo.Type_) == "" || - sInfoPost.TransportInfo.Protocol == "" || - sInfoPost.TransportInfo.Version == "" || - sInfoPost.TransportInfo.Endpoint == nil { - errStr := "Id, Name, Type, Protocol, Version, Endpoint are all mandatory parameters of TransportInfo" - log.Error(errStr) - errHandlerProblemDetails(w, errStr, http.StatusBadRequest) - return - } + if len(sInfoPost.AefProfiles) == 0 || sInfoPost.AefProfiles[0].AefId == "" { + errStr := "Mandatory AefProfiles (AefId) not present" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + transportInfo := sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo + // if sInfoPost.TransportInfo != nil { + if transportInfo.Name == "" || + string(*transportInfo.Type_) == "" || + transportInfo.Protocol == "" || + transportInfo.Version == "" { + errStr := "Id, Name, Type, Protocol, Version, are all mandatory parameters of TransportInfo" + log.Error(errStr) + errHandlerProblemDetails(w, errStr, http.StatusBadRequest) + return + } + // } + + aefProfile := &AefProfile{ + AefId: sInfoPost.AefProfiles[0].AefId, + Versions: sInfoPost.AefProfiles[0].Versions, + InterfaceDescriptions: sInfoPost.AefProfiles[0].InterfaceDescriptions, + VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ + Name: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Name, + Type_: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Type_, + Protocol: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Protocol, + Version: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Version, + Security: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Security, + }, + } + dsInfo := &ServiceApiDescription{ + ApiName: sInfoPost.ApiName, + ApiId: uuid.New().String(), + AefProfiles: []AefProfile{*aefProfile}, + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + Serializer: sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, + State: sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.State, + ScopeOfLocality: sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality, + ConsumedLocalOnly: sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly, + IsLocal: sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.IsLocal, + Category: sInfoPost.VendorSpecificUrnetsimeccapifextserviceInfo.Category, + }, + } + + transportInfo_ := TransportInfo{ + Id: sInfoPost.AefProfiles[0].AefId, // Set this appropriately or generate it + Name: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Name, + Type_: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Type_, + Protocol: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Protocol, + Version: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Version, + Endpoint: sInfoPost.AefProfiles[0].InterfaceDescriptions, // Set the endpoint as required + Security: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Security, } // Create Service sInfo := &ServiceInfo{ - SerInstanceId: uuid.New().String(), - SerName: sInfoPost.SerName, - SerCategory: sInfoPost.SerCategory, - Version: sInfoPost.Version, - State: sInfoPost.State, - TransportInfo: sInfoPost.TransportInfo, - Serializer: sInfoPost.Serializer, - ScopeOfLocality: sInfoPost.ScopeOfLocality, - ConsumedLocalOnly: sInfoPost.ConsumedLocalOnly, + SerInstanceId: dsInfo.ApiId, + SerName: dsInfo.ApiName, + SerCategory: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category, + Version: dsInfo.AefProfiles[0].Versions[0], + State: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State, + TransportInfo: &transportInfo_, + Serializer: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, + ScopeOfLocality: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality, + ConsumedLocalOnly: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly, // although IsLocal is reevaluated when a query is replied to, value stored in sInfo as is for now - IsLocal: sInfoPost.IsLocal, - LivenessInterval: sInfoPost.LivenessInterval, + IsLocal: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.IsLocal, + LivenessInterval: 0, } sInfo.Links = &ServiceInfoLinks{ Self: &LinkType{ -- GitLab From 752196ee285b65d11344b2439d31ae14881562b3 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 13 Aug 2024 10:17:32 +0500 Subject: [PATCH 08/43] Fix minor issue related to conversion of Service information into json --- go-apps/meep-app-enablement/server/capif-mgmt/convert.go | 9 +++++++++ .../server/capif-mgmt/service-mgmt.go | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go index 156f4b202..381f22c26 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -31,6 +31,15 @@ func convertServiceInfoToJson(obj *ServiceInfo) string { return string(jsonInfo) } +func convertServiceInfoToJson_1(obj *ServiceApiDescription) 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) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 20271422f..3c5d652c0 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -408,7 +408,7 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { // Send response w.Header().Set("Location", hostUrl.String()+basePath+"applications/"+appId+"/services/"+sInfo.SerInstanceId) w.WriteHeader(http.StatusCreated) - fmt.Fprint(w, convertServiceInfoToJson(sInfo)) + fmt.Fprint(w, convertServiceInfoToJson_1(dsInfo)) } func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { -- GitLab From d4c8cef3d05637719e54022a03276b8bfea56587 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 13 Aug 2024 14:43:42 +0500 Subject: [PATCH 09/43] Implement logic to retrieves information about a mecService resource via CAPIF --- .../server/capif-mgmt/service-mgmt.go | 58 ++++++++++++------- go-apps/meep-app-enablement/server/routers.go | 7 +++ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 3c5d652c0..963261462 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -253,9 +253,6 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { IsLocal: true, ConsumedLocalOnly: true, }, - // ScopeOfLocality: &locality, - // IsLocal: true, - // ConsumedLocalOnly: true, } decoder := json.NewDecoder(r.Body) err = decoder.Decode(&sInfoPost) @@ -363,12 +360,12 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { } transportInfo_ := TransportInfo{ - Id: sInfoPost.AefProfiles[0].AefId, // Set this appropriately or generate it + Id: sInfoPost.AefProfiles[0].AefId, Name: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Name, Type_: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Type_, Protocol: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Protocol, Version: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Version, - Endpoint: sInfoPost.AefProfiles[0].InterfaceDescriptions, // Set the endpoint as required + Endpoint: sInfoPost.AefProfiles[0].InterfaceDescriptions, Security: sInfoPost.AefProfiles[0].VendorSpecificUrnetsimeccapifexttransportInfo.Security, } @@ -383,9 +380,8 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { Serializer: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, ScopeOfLocality: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality, ConsumedLocalOnly: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly, - // although IsLocal is reevaluated when a query is replied to, value stored in sInfo as is for now - IsLocal: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.IsLocal, - LivenessInterval: 0, + IsLocal: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.IsLocal, + LivenessInterval: 0, } sInfo.Links = &ServiceInfoLinks{ Self: &LinkType{ @@ -615,8 +611,8 @@ func appServicesByIdGET(w http.ResponseWriter, r *http.Request) { log.Info("appServicesByIdGET") w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) - svcId := vars["serviceId"] - appId := vars["appInstanceId"] + svcId := vars["serviceApiId"] + appId := vars["apfId"] mutex.Lock() defer mutex.Unlock() @@ -1273,15 +1269,6 @@ func getServices(w http.ResponseWriter, r *http.Request, appId string) { } serName := q["api-name"] - // var serName []string - // if serNameParam != "" { - // parsedParam, err := parseJSONQueryParam(serNameParam) - // if err != nil { - // errHandlerProblemDetails(w, "Invalid JSON in ser_name", http.StatusBadRequest) - // return - // } - // serName = append(serName, parsedParam.Value) - // } serCategoryIdParam := q.Get("vend-spec-etsi-mec-sercategory-id") var serCategoryId string @@ -1450,8 +1437,39 @@ func getService(w http.ResponseWriter, r *http.Request, appId string, serviceId return } + // Map ServiceInfoList to ServiceApiDescription list + serviceApiDescriptions := make([]ServiceApiDescription, 0) + for _, service := range sInfoList.Services { + aefProfile := AefProfile{ + AefId: service.TransportInfo.Id, + Versions: []string{service.Version}, + InterfaceDescriptions: service.TransportInfo.Endpoint, + VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ + Name: service.TransportInfo.Name, + Type_: service.TransportInfo.Type_, + Protocol: service.TransportInfo.Protocol, + Version: service.TransportInfo.Version, + Security: service.TransportInfo.Security, + }, + } + apiDesc := ServiceApiDescription{ + ApiName: service.SerName, + ApiId: service.SerInstanceId, + AefProfiles: []AefProfile{aefProfile}, + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + Serializer: service.Serializer, + State: service.State, + ScopeOfLocality: service.ScopeOfLocality, + ConsumedLocalOnly: service.ConsumedLocalOnly, + IsLocal: service.IsLocal, + Category: service.SerCategory, + }, + } + serviceApiDescriptions = append(serviceApiDescriptions, apiDesc) + } + // Prepare & send response - jsonResponse, err := json.Marshal(sInfoList.Services[0]) + jsonResponse, err := json.Marshal(serviceApiDescriptions) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index bfc34c6ac..2e382b74b 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -357,6 +357,13 @@ var routes = Routes{ capifMgmt.AppServicesPOST, }, + Route{ + "AppServicesServiceIdGET", + strings.ToUpper("Get"), + "/published-apis/v1/{apfId}/service-apis/{serviceId}", + capifMgmt.AppServicesServiceIdGET, + }, + Route{ "Index", "GET", -- GitLab From 7ddc7f3d23474b1030fe0ae4b8e637d1d8789fae Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 13 Aug 2024 15:36:47 +0500 Subject: [PATCH 10/43] Fix minor issue in router.go file --- go-apps/meep-app-enablement/server/routers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 2e382b74b..552bea469 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -360,7 +360,7 @@ var routes = Routes{ Route{ "AppServicesServiceIdGET", strings.ToUpper("Get"), - "/published-apis/v1/{apfId}/service-apis/{serviceId}", + "/published-apis/v1/{apfId}/service-apis/{serviceApiId}", capifMgmt.AppServicesServiceIdGET, }, -- GitLab From 281942909e12362c7fac9f12a8feaf5350ae9fcd Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 15 Aug 2024 11:50:19 +0500 Subject: [PATCH 11/43] Implement logic to Update(PUT) a service via CAPIF --- .../server/capif-mgmt/service-mgmt.go | 95 +++++++++++++++---- go-apps/meep-app-enablement/server/routers.go | 7 ++ 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 963261462..8264467fd 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -411,8 +411,8 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") log.Info("appServicesByIdPUT") vars := mux.Vars(r) - appId := vars["appInstanceId"] - svcId := vars["serviceId"] + svcId := vars["serviceApiId"] + appId := vars["apfId"] mutex.Lock() defer mutex.Unlock() @@ -454,10 +454,12 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { } // NOTE: Set default values for omitted fields locality := MEC_HOST_LocalityType - sInfo := ServiceInfo{ - ScopeOfLocality: &locality, - IsLocal: true, - ConsumedLocalOnly: true, + sInfo := ServiceApiDescription{ + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + ScopeOfLocality: &locality, + IsLocal: true, + ConsumedLocalOnly: true, + }, } decoder := json.NewDecoder(r.Body) err = decoder.Decode(&sInfo) @@ -467,13 +469,64 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { 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 := &ServiceApiDescription{ + ApiName: sInfo.ApiName, + ApiId: uuid.New().String(), + AefProfiles: []AefProfile{*aefProfile}, + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + 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{ + SerInstanceId: dsInfo.ApiId, + SerName: dsInfo.ApiName, + SerCategory: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category, + Version: dsInfo.AefProfiles[0].Versions[0], + State: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State, + TransportInfo: &transportInfo_, + 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 + 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 + _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) @@ -486,9 +539,9 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { }*/ // Compare service info states & update DB if necessary - *sInfo.State = state - if *sInfo.State != *sInfoPrev.State { - err, retCode := setService(appId, &sInfo, STATE_CHANGED_ServiceAvailabilityNotificationChangeType) + *_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) @@ -497,24 +550,24 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { } // 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) + 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) + deleteLivenessTicker(_sInfo.SerInstanceId) } } else { // No entry - if sInfo.LivenessInterval != 0 { // Create a new entry - createLivenessTicker(sInfo) + if _sInfo.LivenessInterval != 0 { // Create a new entry + createLivenessTicker(_sInfo) } } } // else, nothing to do - sInfo.LivenessInterval = sInfoPrev.LivenessInterval + _sInfo.LivenessInterval = sInfoPrev.LivenessInterval // Send response w.WriteHeader(http.StatusOK) - fmt.Fprint(w, convertServiceInfoToJson(&sInfo)) + fmt.Fprint(w, convertServiceInfoToJson_1(dsInfo)) } func appServicesByIdDELETE(w http.ResponseWriter, r *http.Request) { diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 552bea469..f11334b72 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -364,6 +364,13 @@ var routes = Routes{ capifMgmt.AppServicesServiceIdGET, }, + Route{ + "AppServicesServiceIdPUT", + strings.ToUpper("Put"), + "/published-apis/v1/{apfId}/service-apis/{serviceApiId}", + capifMgmt.AppServicesServiceIdPUT, + }, + Route{ "Index", "GET", -- GitLab From 49b10bc78596105f2662a2afb0873ea097288de0 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 15 Aug 2024 12:19:55 +0500 Subject: [PATCH 12/43] Fix minor issue related to the SerInstanceId --- go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 8264467fd..64bfc8e8d 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -483,7 +483,7 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { } dsInfo := &ServiceApiDescription{ ApiName: sInfo.ApiName, - ApiId: uuid.New().String(), + ApiId: sInfo.ApiId, AefProfiles: []AefProfile{*aefProfile}, VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ Serializer: sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, -- GitLab From 3b6417150fe648eb1817c85fd76cece669c6d09a Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Mon, 19 Aug 2024 10:29:00 +0500 Subject: [PATCH 13/43] Delete AppService by its ID --- .../meep-app-enablement/server/capif-mgmt/service-mgmt.go | 4 ++-- go-apps/meep-app-enablement/server/routers.go | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 64bfc8e8d..38da15f41 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -574,8 +574,8 @@ func appServicesByIdDELETE(w http.ResponseWriter, r *http.Request) { log.Info("appServicesByIdDELETE") w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) - appId := vars["appInstanceId"] - svcId := vars["serviceId"] + svcId := vars["serviceApiId"] + appId := vars["apfId"] mutex.Lock() defer mutex.Unlock() diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index f11334b72..1f878a8de 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -371,6 +371,13 @@ var routes = Routes{ capifMgmt.AppServicesServiceIdPUT, }, + Route{ + "AppServicesServiceIdDELETE", + strings.ToUpper("Delete"), + "/published-apis/v1/{apfId}/service-apis/{serviceApiId}", + capifMgmt.AppServicesServiceIdDELETE, + }, + Route{ "Index", "GET", -- GitLab From 4a18e806368add876ebbd32ba11aff30cdf40f56 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 21 Aug 2024 10:46:30 +0500 Subject: [PATCH 14/43] Add PATCH method to update the newly created service --- .../server/capif-mgmt/api_mec_service_mgmt.go | 4 + .../server/capif-mgmt/convert.go | 9 + .../model_mec_service_info_capif_ext_patch.go | 24 +++ .../model_service_api_description_patch.go | 14 ++ .../server/capif-mgmt/service-mgmt.go | 159 ++++++++++++++++++ go-apps/meep-app-enablement/server/routers.go | 7 + 6 files changed, 217 insertions(+) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext_patch.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go index e230ebd1a..8f1fca70e 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go @@ -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) } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go index 381f22c26..552e31521 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -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) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext_patch.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext_patch.go new file mode 100644 index 000000000..23aa2fd07 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_mec_service_info_capif_ext_patch.go @@ -0,0 +1,24 @@ +/* + * 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"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go new file mode 100644 index 000000000..cf0cf27f0 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go @@ -0,0 +1,14 @@ +/* + * 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"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 38da15f41..81728febf 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -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") diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 1f878a8de..ce05174fa 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -371,6 +371,13 @@ var routes = Routes{ capifMgmt.AppServicesServiceIdPUT, }, + Route{ + "AppServicesServiceIdPATCH", + strings.ToUpper("Patch"), + "/published-apis/v1/{apfId}/service-apis/{serviceApiId}", + capifMgmt.AppServicesServiceIdPATCH, + }, + Route{ "AppServicesServiceIdDELETE", strings.ToUpper("Delete"), -- GitLab From 3c4d3918c9f0fa0aa5dbdbabeb77254d71311817 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 21 Aug 2024 11:17:30 +0500 Subject: [PATCH 15/43] make changes to allow PATCH method in mec sandbox enviorment --- go-apps/meep-app-enablement/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/main.go b/go-apps/meep-app-enablement/main.go index cd9586633..8ab902d2b 100644 --- a/go-apps/meep-app-enablement/main.go +++ b/go-apps/meep-app-enablement/main.go @@ -69,7 +69,7 @@ func main() { // Start Edge Platform App Enablement Service REST API Server router := server.NewRouter() - methods := handlers.AllowedMethods([]string{"OPTIONS", "DELETE", "GET", "HEAD", "POST", "PUT"}) + methods := handlers.AllowedMethods([]string{"OPTIONS", "DELETE", "GET", "HEAD", "POST", "PUT", "PATCH"}) header := handlers.AllowedHeaders([]string{"content-type"}) log.Fatal(http.ListenAndServe(":80", handlers.CORS(methods, header)(router))) run = false -- GitLab From 80802802d767a685fcb870546b6828f061acc7b4 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 22 Aug 2024 10:50:00 +0500 Subject: [PATCH 16/43] fix issue releated to the PATCH method in CAPIF-mgmt --- .../server/capif-mgmt/service-mgmt.go | 49 ++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 81728febf..c885c6f8b 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -547,6 +547,13 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, err.Error(), retCode) return } + } else { + err, retCode := setService(appId, &_sInfo, ATTRIBUTES_CHANGED_ServiceAvailabilityNotificationChangeType) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), retCode) + return + } } // Compare LivenessInterval @@ -632,22 +639,7 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { 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, @@ -658,20 +650,14 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { }, } - // 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{ + SerInstanceId: sInfoPrev.SerInstanceId, + SerName: sInfoPrev.SerName, + Version: sInfoPrev.Version, SerCategory: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category, State: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State, + TransportInfo: sInfoPrev.TransportInfo, Serializer: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, ScopeOfLocality: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality, ConsumedLocalOnly: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly, @@ -681,8 +667,8 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { // 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 + // 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 @@ -698,7 +684,7 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { }*/ // Compare service info states & update DB if necessary - *_sInfo.State = state + // *_sInfo.State = state if *_sInfo.State != *sInfoPrev.State { err, retCode := setService(appId, &_sInfo, STATE_CHANGED_ServiceAvailabilityNotificationChangeType) if err != nil { @@ -706,6 +692,13 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, err.Error(), retCode) return } + } else { + err, retCode := setService(appId, &_sInfo, ATTRIBUTES_CHANGED_ServiceAvailabilityNotificationChangeType) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), retCode) + return + } } // Compare LivenessInterval -- GitLab From a563490d2b317d0db518fdc6152dfad4ec78e0be Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 27 Aug 2024 10:20:52 +0000 Subject: [PATCH 17/43] Add specific routes for CAPIF event subscription --- charts/meep-app-enablement/values-template.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/charts/meep-app-enablement/values-template.yaml b/charts/meep-app-enablement/values-template.yaml index e9b2391e9..f279333ac 100644 --- a/charts/meep-app-enablement/values-template.yaml +++ b/charts/meep-app-enablement/values-template.yaml @@ -48,11 +48,13 @@ ingress: - /{{.SandboxName}}/{{.MepName}}/mec_service_mgmt - /{{.SandboxName}}/{{.MepName}}/service-apis - /{{.SandboxName}}/{{.MepName}}/published-apis + - /{{.SandboxName}}/{{.MepName}}/capif-events {{- else }} - /{{.SandboxName}}/mec_app_support - /{{.SandboxName}}/mec_service_mgmt - /{{.SandboxName}}/service-apis - /{{.SandboxName}}/published-apis + - /{{.SandboxName}}/capif-events {{- end }} annotations: kubernetes.io/ingress.class: nginx @@ -63,12 +65,14 @@ ingress: rewrite ^/{{ .SandboxName }}/{{.MepName}}/mec_service_mgmt(/|$)(.*)$ /mec_service_mgmt/$2 break; rewrite ^/{{ .SandboxName }}/{{.MepName}}/service-apis(/|$)(.*)$ /service-apis/$2 break; rewrite ^/{{ .SandboxName }}/{{.MepName}}/published-apis(/|$)(.*)$ /published-apis/$2 break; + rewrite ^/{{ .SandboxName }}/{{.MepName}}/capif-events(/|$)(.*)$ /capif-events/$2 break; {{- else }} nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^/{{ .SandboxName }}/mec_app_support(/|$)(.*)$ /mec_app_support/$2 break; rewrite ^/{{ .SandboxName }}/mec_service_mgmt(/|$)(.*)$ /mec_service_mgmt/$2 break; rewrite ^/{{ .SandboxName }}/service-apis(/|$)(.*)$ /service-apis/$2 break; rewrite ^/{{ .SandboxName }}/published-apis(/|$)(.*)$ /published-apis/$2 break; + rewrite ^/{{ .SandboxName }}/capif-events(/|$)(.*)$ /capif-events/$2 break; {{- end }} {{- if .AuthEnabled }} nginx.ingress.kubernetes.io/auth-url: https://$http_host/auth/v1/authenticate?svc=meep-app-enablement&sbox={{.SandboxName}}&mep={{.MepName}} -- GitLab From 2a73469372303ef9300db0651366082d3cd57a0a Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 27 Aug 2024 15:23:33 +0500 Subject: [PATCH 18/43] Update router.go file to add the route for the Capif event subscription --- go-apps/meep-app-enablement/server/routers.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index ce05174fa..9a5da3b69 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -385,6 +385,13 @@ var routes = Routes{ capifMgmt.AppServicesServiceIdDELETE, }, + Route{ + "ApplicationsSubscriptionsPOST", + strings.ToUpper("Post"), + "/capif-events/v1/{subscriberId}/subscriptions ", + capifMgmt.ApplicationsSubscriptionsPOST, + }, + Route{ "Index", "GET", -- GitLab From e449c845ef6e392710aa699a93c13a2ddecaf553 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 27 Aug 2024 15:44:10 +0500 Subject: [PATCH 19/43] Fix minor issue in router file --- go-apps/meep-app-enablement/server/routers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 9a5da3b69..9ce35bb86 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -388,7 +388,7 @@ var routes = Routes{ Route{ "ApplicationsSubscriptionsPOST", strings.ToUpper("Post"), - "/capif-events/v1/{subscriberId}/subscriptions ", + "/capif-events/v1/{subscriberId}/subscriptions", capifMgmt.ApplicationsSubscriptionsPOST, }, -- GitLab From d6b127360731604f9034af64757705ab96237fc7 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 28 Aug 2024 12:47:00 +0500 Subject: [PATCH 20/43] Implement the logic to create the CAPIF event subscription (POST) --- .../api/capif-mgmt/swagger.yaml | 13 +++ .../server/capif-mgmt/convert.go | 9 ++ .../server/capif-mgmt/model_capif_event.go | 20 ++++ .../capif-mgmt/model_capif_event_filter.go | 15 +++ .../capif-mgmt/model_event_subscription.go | 22 ++++ ...ability_notification_service_references.go | 2 +- .../server/capif-mgmt/service-mgmt.go | 102 +++++++++--------- 7 files changed, 131 insertions(+), 52 deletions(-) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_filter.go create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription.go diff --git a/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml b/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml index e803dcdbe..b2cd8178b 100644 --- a/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml +++ b/go-apps/meep-app-enablement/api/capif-mgmt/swagger.yaml @@ -955,6 +955,15 @@ components: description: | URI to which notifications will be sent. Shall be set to the value of the "callbackReference" attribute in the "SerAvailabilityNotificationSubscription" structure. format: uri + CAPIFEventFilter: + title: CAPIFEventFilter + type: object + properties: + apiIds: + type: array + description: Identifiers of service instances about which to report events. + items: + type: string EventSubscription: required: - events @@ -965,6 +974,10 @@ components: type: array items: $ref: '#/components/schemas/CAPIFEvent' + eventFilters: + type: array + items: + $ref: '#/components/schemas/CAPIFEventFilter' notificationDestination: type: string description: | diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go index 552e31521..5da1e2737 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -68,6 +68,15 @@ func convertSerAvailabilityNotifSubToJson(obj *SerAvailabilityNotificationSubscr return string(jsonInfo) } +func convertSerAvailabilityNotifSubToJson_1(obj *EventSubscription) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + func convertJsonToSerAvailabilityNotifSub(jsonData string) *SerAvailabilityNotificationSubscription { var obj SerAvailabilityNotificationSubscription err := json.Unmarshal([]byte(jsonData), &obj) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event.go new file mode 100644 index 000000000..fc5c7bcac --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event.go @@ -0,0 +1,20 @@ +/* + * 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 + +// CapifEvent : The CAPIFEvent data type represents the type of events for which the subscription is made. +type CapifEvent string + +// List of CAPIFEvent +const ( + AVAILABLE CapifEvent = "SERVICE_API_AVAILABLE" + UNAVAILABLE CapifEvent = "SERVICE_API_UNAVAILABLE" + UPDATE CapifEvent = "SERVICE_API_UPDATE" +) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_filter.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_filter.go new file mode 100644 index 000000000..5d11b2da8 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_filter.go @@ -0,0 +1,15 @@ +/* + * 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 CapifEventFilter struct { + // Identifiers of service instances about which to report events. + ApiIds []string `json:"apiIds,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription.go new file mode 100644 index 000000000..1f8fe22ca --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription.go @@ -0,0 +1,22 @@ +/* + * 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 EventSubscription struct { + Events []CapifEvent `json:"events"` + + EventFilters []CapifEventFilter `json:"eventFilters,omitempty"` + // URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response. + NotificationDestination string `json:"notificationDestination"` + + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + + WebsocketNotifConfig string `json:"websocketNotifConfig,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go index 9315e529d..025455a7e 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_availability_notification_service_references.go @@ -19,5 +19,5 @@ type ServiceAvailabilityNotificationServiceReferences struct { State *ServiceState `json:"state"` - ChangeType *ServiceAvailabilityNotificationChangeType `json:"changeType"` + ChangeType *CapifEvent `json:"changeType"` } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index c885c6f8b..1e9236315 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -394,7 +394,7 @@ func appServicesPOST(w http.ResponseWriter, r *http.Request) { } } - err, retCode := setService(appId, sInfo, ADDED_ServiceAvailabilityNotificationChangeType) + err, retCode := setService(appId, sInfo, AVAILABLE) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), retCode) @@ -541,14 +541,14 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { // Compare service info states & update DB if necessary *_sInfo.State = state if *_sInfo.State != *sInfoPrev.State { - err, retCode := setService(appId, &_sInfo, STATE_CHANGED_ServiceAvailabilityNotificationChangeType) + err, retCode := setService(appId, &_sInfo, UPDATE) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), retCode) return } } else { - err, retCode := setService(appId, &_sInfo, ATTRIBUTES_CHANGED_ServiceAvailabilityNotificationChangeType) + err, retCode := setService(appId, &_sInfo, UPDATE) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), retCode) @@ -686,14 +686,14 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { // Compare service info states & update DB if necessary // *_sInfo.State = state if *_sInfo.State != *sInfoPrev.State { - err, retCode := setService(appId, &_sInfo, STATE_CHANGED_ServiceAvailabilityNotificationChangeType) + err, retCode := setService(appId, &_sInfo, UPDATE) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), retCode) return } } else { - err, retCode := setService(appId, &_sInfo, ATTRIBUTES_CHANGED_ServiceAvailabilityNotificationChangeType) + err, retCode := setService(appId, &_sInfo, UPDATE) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), retCode) @@ -769,7 +769,7 @@ func appServicesByIdDELETE(w http.ResponseWriter, r *http.Request) { } // Notify remote listeners (except if global instance) - changeType := REMOVED_ServiceAvailabilityNotificationChangeType + changeType := UNAVAILABLE if mepName != globalMepName { sendSvcUpdateMsg(sInfoJson, appId, mepName, string(changeType)) } @@ -918,7 +918,7 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) return } - var serAvailNotifSub SerAvailabilityNotificationSubscription + var serAvailNotifSub EventSubscription decoder := json.NewDecoder(r.Body) err = decoder.Decode(&serAvailNotifSub) if err != nil { @@ -928,41 +928,22 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { } // Validate mandatory properties - if serAvailNotifSub.CallbackReference == "" { - log.Error("Mandatory CallbackReference parameter not present") - errHandlerProblemDetails(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest) - return - } - if serAvailNotifSub.SubscriptionType != SER_AVAILABILITY_NOTIF_SUB_TYPE { - log.Error("SubscriptionType shall be SerAvailabilityNotificationSubscription") - errHandlerProblemDetails(w, "SubscriptionType shall be SerAvailabilityNotificationSubscription", http.StatusBadRequest) + if serAvailNotifSub.NotificationDestination == "" { + log.Error("Mandatory NotificationDestination parameter not present") + errHandlerProblemDetails(w, "Mandatory NotificationDestination parameter not present", http.StatusBadRequest) return } + // if serAvailNotifSub.SubscriptionType != SER_AVAILABILITY_NOTIF_SUB_TYPE { + // log.Error("SubscriptionType shall be SerAvailabilityNotificationSubscription") + // errHandlerProblemDetails(w, "SubscriptionType shall be SerAvailabilityNotificationSubscription", http.StatusBadRequest) + // return + // } // Validate Service filter params - if serAvailNotifSub.FilteringCriteria != nil { + if serAvailNotifSub.EventFilters != nil { nbMutuallyExclusiveParams := 0 - if serAvailNotifSub.FilteringCriteria.SerInstanceIds != nil { - if len(serAvailNotifSub.FilteringCriteria.SerInstanceIds) > 0 { - nbMutuallyExclusiveParams++ - } - } - if serAvailNotifSub.FilteringCriteria.SerNames != nil { - if len(serAvailNotifSub.FilteringCriteria.SerNames) > 0 { - nbMutuallyExclusiveParams++ - } - } - if serAvailNotifSub.FilteringCriteria.SerCategories != nil { - for _, categoryRef := range serAvailNotifSub.FilteringCriteria.SerCategories { - errStr := validateCategoryRef(&categoryRef) - if errStr != "" { - log.Error(errStr) - errHandlerProblemDetails(w, errStr, http.StatusBadRequest) - return - } - } - - if len(serAvailNotifSub.FilteringCriteria.SerCategories) > 0 { + for _, filter := range serAvailNotifSub.EventFilters { + if filter.ApiIds != nil && len(filter.ApiIds) > 0 { nbMutuallyExclusiveParams++ } } @@ -977,25 +958,29 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { // Get a new subscription ID subId := subMgr.GenerateSubscriptionId() - // Set resource link - serAvailNotifSub.Links = &Self{ - Self: &LinkType{ - Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId, - }, - } + // // Set resource link + // serAvailNotifSub.Links = &Self{ + // Self: &LinkType{ + // Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId, + // }, + // } // Create & store subscription - subCfg := newSerAvailabilityNotifSubCfg(&serAvailNotifSub, subId, appId) - jsonSub := convertSerAvailabilityNotifSubToJson(&serAvailNotifSub) + subCfg := newSerAvailabilityNotifSubCfg_1(&serAvailNotifSub, subId, appId) + jsonSub := convertSerAvailabilityNotifSubToJson_1(&serAvailNotifSub) _, err = subMgr.CreateSubscription(subCfg, jsonSub) if err != nil { log.Error("Failed to create subscription") errHandlerProblemDetails(w, "Failed to create subscription", http.StatusInternalServerError) return } - + // Self: + // &LinkType{ + // Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId, + // } + hrefUrl := hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId // Send response - w.Header().Set("Location", serAvailNotifSub.Links.Self.Href) + w.Header().Set("Location", hrefUrl) w.WriteHeader(http.StatusCreated) fmt.Fprint(w, jsonSub) } @@ -1369,7 +1354,7 @@ func deleteService(key string, sInfoJson string, data interface{}) error { sInfo := convertJsonToServiceInfo(sInfoJson) // Notify remote listeners (except if global instance) - changeType := REMOVED_ServiceAvailabilityNotificationChangeType + changeType := UNAVAILABLE if mepName != globalMepName { sendSvcUpdateMsg(sInfoJson, appId, mepName, string(changeType)) } @@ -1395,7 +1380,7 @@ func delServiceById(appId string, svcId string) error { return nil } -func setService(appId string, sInfo *ServiceInfo, changeType ServiceAvailabilityNotificationChangeType) (err error, retCode int) { +func setService(appId string, sInfo *ServiceInfo, changeType CapifEvent) (err error, retCode int) { // Create/update service sInfoJson := convertServiceInfoToJson(sInfo) key := baseKey + "app:" + appId + ":svc:" + sInfo.SerInstanceId @@ -1823,10 +1808,10 @@ func processSvcUpdate(sInfoJson, mep, changeType string) { sInfo := convertJsonToServiceInfo(sInfoJson) // Check if notifications must be sent - checkSerAvailNotification(sInfo, mep, ServiceAvailabilityNotificationChangeType(changeType)) + checkSerAvailNotification(sInfo, mep, CapifEvent(changeType)) } -func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType ServiceAvailabilityNotificationChangeType) { +func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifEvent) { // Set IsLocal flag if *sInfo.ScopeOfLocality == MEC_SYSTEM_LocalityType || (mep != "" && mep == mepName) { sInfo.IsLocal = true @@ -2081,6 +2066,21 @@ func newSerAvailabilityNotifSubCfg(sub *SerAvailabilityNotificationSubscription, return subCfg } +func newSerAvailabilityNotifSubCfg_1(sub *EventSubscription, subId string, appId string) *subs.SubscriptionCfg { + subCfg := &subs.SubscriptionCfg{ + Id: subId, + AppId: appId, + Type: SER_AVAILABILITY_NOTIF_SUB_TYPE, + Self: "", + NotifyUrl: sub.NotificationDestination, + ExpiryTime: nil, + PeriodicInterval: 0, + RequestTestNotif: false, + RequestWebsocketUri: false, + } + return subCfg +} + func errHandlerProblemDetails(w http.ResponseWriter, error string, code int) { var pd ProblemDetails pd.Detail = error -- GitLab From af69016dde806cc23b70e9e4f9a15beea3a15cbe Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 29 Aug 2024 10:38:31 +0500 Subject: [PATCH 21/43] Fix minor issue to get the vars from the request --- go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 1e9236315..47de735f3 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -887,7 +887,7 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) - appId := vars["appInstanceId"] + appId := vars["subscriberId"] mutex.Lock() defer mutex.Unlock() -- GitLab From 38eeef2b92456bc6a7a8ae54805f7ef305f637ec Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 30 Aug 2024 10:10:22 +0500 Subject: [PATCH 22/43] Implement logic to send the sotification when the subscription created --- .../server/capif-mgmt/convert.go | 19 ++ .../capif-mgmt/model_event_notification.go | 15 ++ .../server/capif-mgmt/service-mgmt.go | 165 ++++++++++-------- 3 files changed, 127 insertions(+), 72 deletions(-) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go index 5da1e2737..73bd9fc98 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -87,6 +87,16 @@ func convertJsonToSerAvailabilityNotifSub(jsonData string) *SerAvailabilityNotif return &obj } +func convertJsonToSerAvailabilityNotifSub_1(jsonData string) *EventSubscription { + var obj EventSubscription + err := json.Unmarshal([]byte(jsonData), &obj) + if err != nil { + log.Error(err.Error()) + return nil + } + return &obj +} + func convertServiceAvailabilityNotifToJson(obj *ServiceAvailabilityNotification) string { jsonInfo, err := json.Marshal(*obj) if err != nil { @@ -96,6 +106,15 @@ func convertServiceAvailabilityNotifToJson(obj *ServiceAvailabilityNotification) return string(jsonInfo) } +func convertServiceAvailabilityNotifToJson_1(obj *EventNotification) string { + jsonInfo, err := json.Marshal(*obj) + if err != nil { + log.Error(err.Error()) + return "" + } + return string(jsonInfo) +} + func convertProblemDetailsToJson(obj *ProblemDetails) string { jsonInfo, err := json.Marshal(*obj) if err != nil { diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go new file mode 100644 index 000000000..2c1c22e1d --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go @@ -0,0 +1,15 @@ +/* + * 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 EventNotification struct { + // The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE, and SERVICE_API_UPDATE defined in the type \"CAPIFEvent\" shall be supported. The remaining values of that type need not be supported. + Events []CapifEvent `json:"events,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 47de735f3..c98599d6c 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1835,21 +1835,23 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE for _, sub := range subList { // Unmarshal original JSON subscription - origSub := convertJsonToSerAvailabilityNotifSub(sub.JsonSubOrig) + origSub := convertJsonToSerAvailabilityNotifSub_1(sub.JsonSubOrig) if origSub == nil { continue } // Check subscription filter criteria - if origSub.FilteringCriteria != nil { - + if len(origSub.EventFilters) > 0 { + found := false // Service Instance IDs - if origSub.FilteringCriteria.SerInstanceIds != nil && len(origSub.FilteringCriteria.SerInstanceIds) > 0 { - found := false - for _, serInstanceId := range origSub.FilteringCriteria.SerInstanceIds { - if serInstanceId == sInfo.SerInstanceId { - found = true - break + for _, eventFilter := range origSub.EventFilters { + // Check if ApiIds (replacing SerInstanceIds) match + if len(eventFilter.ApiIds) > 0 { + for _, apiId := range eventFilter.ApiIds { + if apiId == sInfo.SerInstanceId { // Compare with the current Service Instance ID (now ApiId) + found = true + break + } } } if !found { @@ -1858,80 +1860,99 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE } // Service Names - if origSub.FilteringCriteria.SerNames != nil && len(origSub.FilteringCriteria.SerNames) > 0 { - found := false - for _, serName := range origSub.FilteringCriteria.SerNames { - if serName == sInfo.SerName { - found = true - break - } - } - if !found { - continue - } - } + // if origSub.FilteringCriteria.SerNames != nil && len(origSub.FilteringCriteria.SerNames) > 0 { + // found := false + // for _, serName := range origSub.FilteringCriteria.SerNames { + // if serName == sInfo.SerName { + // found = true + // break + // } + // } + // if !found { + // continue + // } + // } // Service Categories - if origSub.FilteringCriteria.SerCategories != nil && len(origSub.FilteringCriteria.SerCategories) > 0 { - found := false - for _, serCategory := range origSub.FilteringCriteria.SerCategories { - if serCategory.Href == sInfo.SerCategory.Href && - serCategory.Id == sInfo.SerCategory.Id && - serCategory.Name == sInfo.SerCategory.Name && - serCategory.Version == sInfo.SerCategory.Version { - found = true - break - } - } - if !found { - continue - } - } + // if origSub.FilteringCriteria.SerCategories != nil && len(origSub.FilteringCriteria.SerCategories) > 0 { + // found := false + // for _, serCategory := range origSub.FilteringCriteria.SerCategories { + // if serCategory.Href == sInfo.SerCategory.Href && + // serCategory.Id == sInfo.SerCategory.Id && + // serCategory.Name == sInfo.SerCategory.Name && + // serCategory.Version == sInfo.SerCategory.Version { + // found = true + // break + // } + // } + // if !found { + // continue + // } + // } // Service states - if origSub.FilteringCriteria.States != nil && len(origSub.FilteringCriteria.States) > 0 { - found := false - for _, serState := range origSub.FilteringCriteria.States { - if serState == *sInfo.State { - found = true - break - } - } - if !found { - continue - } - } - - // Service locality - if origSub.FilteringCriteria.IsLocal && !sInfo.IsLocal { - continue - } + // if origSub.FilteringCriteria.States != nil && len(origSub.FilteringCriteria.States) > 0 { + // found := false + // for _, serState := range origSub.FilteringCriteria.States { + // if serState == *sInfo.State { + // found = true + // break + // } + // } + // if !found { + // continue + // } + // } + + // // Service locality + // if origSub.FilteringCriteria.IsLocal && !sInfo.IsLocal { + // continue + // } } - - // Create notification payload - notif := &ServiceAvailabilityNotification{ - NotificationType: SER_AVAILABILITY_NOTIF_TYPE, - Links: &Subscription{ - Subscription: &LinkType{ - Href: sub.Cfg.Self, - }, - }, + // Create a new EventNotification instance + notif := &EventNotification{} + + // Set the event type based on changeType + var eventType CapifEvent + switch changeType { + case "SERVICE_API_AVAILABLE": + eventType = AVAILABLE + case "SERVICE_API_UNAVAILABLE": + eventType = UNAVAILABLE + case "SERVICE_API_UPDATE": + eventType = UPDATE + default: + // Handle any default case or errors } - serAvailabilityRef := ServiceAvailabilityNotificationServiceReferences{ - Link: &LinkType{ - Href: hostUrl.String() + basePath + "services/" + sInfo.SerInstanceId, - }, - SerName: sInfo.SerName, - SerInstanceId: sInfo.SerInstanceId, - State: sInfo.State, - ChangeType: &changeType, + + // If eventType is set, append it to the Events slice + if eventType != "" { + notif.Events = append(notif.Events, eventType) } - notif.ServiceReferences = append(notif.ServiceReferences, serAvailabilityRef) + // // Create notification payload + // notif := &ServiceAvailabilityNotification{ + // NotificationType: SER_AVAILABILITY_NOTIF_TYPE, + // Links: &Subscription{ + // Subscription: &LinkType{ + // Href: sub.Cfg.Self, + // }, + // }, + // } + // serAvailabilityRef := ServiceAvailabilityNotificationServiceReferences{ + // Link: &LinkType{ + // Href: hostUrl.String() + basePath + "services/" + sInfo.SerInstanceId, + // }, + // SerName: sInfo.SerName, + // SerInstanceId: sInfo.SerInstanceId, + // State: sInfo.State, + // ChangeType: &changeType, + // } + // notif.ServiceReferences = append(notif.ServiceReferences, serAvailabilityRef) // Send notification go func(sub *subs.Subscription) { log.Info("Sending Service Availability notification (" + sub.Cfg.Id + ") for " + string(changeType)) - err := subMgr.SendNotification(sub, []byte(convertServiceAvailabilityNotifToJson(notif))) + err := subMgr.SendNotification(sub, []byte(convertServiceAvailabilityNotifToJson_1(notif))) if err != nil { log.Error("Failed to send Service Availability notif with err: ", err.Error()) } -- GitLab From 3d71830559a1acb408ab6ab4939e8855cffb480c Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 30 Aug 2024 12:03:08 +0500 Subject: [PATCH 23/43] Remove the unnecessary code and add the subscription ID in event notification --- .../capif-mgmt/model_event_notification.go | 2 + .../server/capif-mgmt/service-mgmt.go | 94 ++----------------- 2 files changed, 10 insertions(+), 86 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go index 2c1c22e1d..e85d678ae 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go @@ -12,4 +12,6 @@ package server type EventNotification struct { // The values SERVICE_API_AVAILABLE, SERVICE_API_UNAVAILABLE, and SERVICE_API_UPDATE defined in the type \"CAPIFEvent\" shall be supported. The remaining values of that type need not be supported. Events []CapifEvent `json:"events,omitempty"` + // Identifier of the subscription resource to which the notification is related + SubscriptionId string `json:"subscriptionId"` } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index c98599d6c..8083e4937 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -933,16 +933,16 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, "Mandatory NotificationDestination parameter not present", http.StatusBadRequest) return } - // if serAvailNotifSub.SubscriptionType != SER_AVAILABILITY_NOTIF_SUB_TYPE { - // log.Error("SubscriptionType shall be SerAvailabilityNotificationSubscription") - // errHandlerProblemDetails(w, "SubscriptionType shall be SerAvailabilityNotificationSubscription", http.StatusBadRequest) - // return - // } // Validate Service filter params if serAvailNotifSub.EventFilters != nil { nbMutuallyExclusiveParams := 0 for _, filter := range serAvailNotifSub.EventFilters { + if len(filter.ApiIds) == 0 { + log.Error("Mandatory ApiIds(serInstanceIds) parameter not present") + errHandlerProblemDetails(w, "Mandatory ApiIds(serInstanceIds) parameter not present", http.StatusBadRequest) + return + } if filter.ApiIds != nil && len(filter.ApiIds) > 0 { nbMutuallyExclusiveParams++ } @@ -958,13 +958,6 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { // Get a new subscription ID subId := subMgr.GenerateSubscriptionId() - // // Set resource link - // serAvailNotifSub.Links = &Self{ - // Self: &LinkType{ - // Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId, - // }, - // } - // Create & store subscription subCfg := newSerAvailabilityNotifSubCfg_1(&serAvailNotifSub, subId, appId) jsonSub := convertSerAvailabilityNotifSubToJson_1(&serAvailNotifSub) @@ -974,10 +967,6 @@ func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, "Failed to create subscription", http.StatusInternalServerError) return } - // Self: - // &LinkType{ - // Href: hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId, - // } hrefUrl := hostUrl.String() + basePath + "applications/" + appId + "/subscriptions/" + subId // Send response w.Header().Set("Location", hrefUrl) @@ -1858,59 +1847,11 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE continue } } - - // Service Names - // if origSub.FilteringCriteria.SerNames != nil && len(origSub.FilteringCriteria.SerNames) > 0 { - // found := false - // for _, serName := range origSub.FilteringCriteria.SerNames { - // if serName == sInfo.SerName { - // found = true - // break - // } - // } - // if !found { - // continue - // } - // } - - // Service Categories - // if origSub.FilteringCriteria.SerCategories != nil && len(origSub.FilteringCriteria.SerCategories) > 0 { - // found := false - // for _, serCategory := range origSub.FilteringCriteria.SerCategories { - // if serCategory.Href == sInfo.SerCategory.Href && - // serCategory.Id == sInfo.SerCategory.Id && - // serCategory.Name == sInfo.SerCategory.Name && - // serCategory.Version == sInfo.SerCategory.Version { - // found = true - // break - // } - // } - // if !found { - // continue - // } - // } - - // Service states - // if origSub.FilteringCriteria.States != nil && len(origSub.FilteringCriteria.States) > 0 { - // found := false - // for _, serState := range origSub.FilteringCriteria.States { - // if serState == *sInfo.State { - // found = true - // break - // } - // } - // if !found { - // continue - // } - // } - - // // Service locality - // if origSub.FilteringCriteria.IsLocal && !sInfo.IsLocal { - // continue - // } } // Create a new EventNotification instance - notif := &EventNotification{} + notif := &EventNotification{ + SubscriptionId: sub.Cfg.Id, + } // Set the event type based on changeType var eventType CapifEvent @@ -1929,25 +1870,6 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE if eventType != "" { notif.Events = append(notif.Events, eventType) } - // // Create notification payload - // notif := &ServiceAvailabilityNotification{ - // NotificationType: SER_AVAILABILITY_NOTIF_TYPE, - // Links: &Subscription{ - // Subscription: &LinkType{ - // Href: sub.Cfg.Self, - // }, - // }, - // } - // serAvailabilityRef := ServiceAvailabilityNotificationServiceReferences{ - // Link: &LinkType{ - // Href: hostUrl.String() + basePath + "services/" + sInfo.SerInstanceId, - // }, - // SerName: sInfo.SerName, - // SerInstanceId: sInfo.SerInstanceId, - // State: sInfo.State, - // ChangeType: &changeType, - // } - // notif.ServiceReferences = append(notif.ServiceReferences, serAvailabilityRef) // Send notification go func(sub *subs.Subscription) { -- GitLab From 75a88eb9a7a6bbf26bbf8bec07af969f91b86aba Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 30 Aug 2024 12:47:30 +0500 Subject: [PATCH 24/43] Add service instance id in the event notification and implement its logic --- .../server/capif-mgmt/model_capif_event_detail.go | 15 +++++++++++++++ .../server/capif-mgmt/model_event_notification.go | 2 ++ .../server/capif-mgmt/service-mgmt.go | 5 +++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_detail.go diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_detail.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_detail.go new file mode 100644 index 000000000..1663a9d27 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_capif_event_detail.go @@ -0,0 +1,15 @@ +/* + * 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 CapifEventDetail struct { + ServiceApiDescriptions []ServiceApiDescription `json:"serviceApiDescriptions,omitempty"` + ApiIds []string `json:"apiIds,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go index e85d678ae..fdfa66df4 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_notification.go @@ -14,4 +14,6 @@ type EventNotification struct { Events []CapifEvent `json:"events,omitempty"` // Identifier of the subscription resource to which the notification is related SubscriptionId string `json:"subscriptionId"` + // Detailed information for the event, conditionally included + EventDetail *CapifEventDetail `json:"eventDetail,omitempty"` } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 8083e4937..b675cd024 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1852,7 +1852,8 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE notif := &EventNotification{ SubscriptionId: sub.Cfg.Id, } - + event_detail := &CapifEventDetail{} + event_detail.ApiIds = append(event_detail.ApiIds, sInfo.SerInstanceId) // Set the event type based on changeType var eventType CapifEvent switch changeType { @@ -1863,7 +1864,7 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE case "SERVICE_API_UPDATE": eventType = UPDATE default: - // Handle any default case or errors + continue } // If eventType is set, append it to the Events slice -- GitLab From b0375801b099fa34f09d1832197dafdbac0eb36d Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 30 Aug 2024 12:49:59 +0500 Subject: [PATCH 25/43] fix minor issue Add event detail in event notification --- .../meep-app-enablement/server/capif-mgmt/service-mgmt.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index b675cd024..b65cef6cc 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1848,12 +1848,14 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE } } } + + event_detail := &CapifEventDetail{} + event_detail.ApiIds = append(event_detail.ApiIds, sInfo.SerInstanceId) // Create a new EventNotification instance notif := &EventNotification{ SubscriptionId: sub.Cfg.Id, + EventDetail: event_detail, } - event_detail := &CapifEventDetail{} - event_detail.ApiIds = append(event_detail.ApiIds, sInfo.SerInstanceId) // Set the event type based on changeType var eventType CapifEvent switch changeType { -- GitLab From b4f22c4dc7f687af14e6c0594ba6b568d412bdf8 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 3 Sep 2024 11:09:32 +0500 Subject: [PATCH 26/43] Add serviceApiDescription in event notification --- .../server/capif-mgmt/service-mgmt.go | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index b65cef6cc..50f27bb62 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1848,8 +1848,35 @@ func checkSerAvailNotification(sInfo *ServiceInfo, mep string, changeType CapifE } } } + versions := []string{sInfo.Version} + aefProfile := &AefProfile{ + AefId: sInfo.TransportInfo.Id, + Versions: versions, + InterfaceDescriptions: sInfo.TransportInfo.Endpoint, + VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ + Name: sInfo.TransportInfo.Name, + Type_: sInfo.TransportInfo.Type_, + Protocol: sInfo.TransportInfo.Protocol, + Version: sInfo.TransportInfo.Version, + Security: sInfo.TransportInfo.Security, + }, + } + dsInfo := &ServiceApiDescription{ + ApiName: sInfo.SerName, + ApiId: sInfo.SerInstanceId, + AefProfiles: []AefProfile{*aefProfile}, + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + Serializer: sInfo.Serializer, + State: sInfo.State, + ScopeOfLocality: sInfo.ScopeOfLocality, + ConsumedLocalOnly: sInfo.ConsumedLocalOnly, + IsLocal: sInfo.IsLocal, + Category: sInfo.SerCategory, + }, + } event_detail := &CapifEventDetail{} + event_detail.ServiceApiDescriptions = append(event_detail.ServiceApiDescriptions, *dsInfo) event_detail.ApiIds = append(event_detail.ApiIds, sInfo.SerInstanceId) // Create a new EventNotification instance notif := &EventNotification{ -- GitLab From 5c3aadf4f0d6d2365056ef4169cb070bd1d35e95 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 4 Sep 2024 15:12:46 +0500 Subject: [PATCH 27/43] Add the Put method in CAPIF event subscription --- .../server/capif-mgmt/api_mec_service_mgmt.go | 4 +- .../server/capif-mgmt/convert.go | 17 ++++ .../server/capif-mgmt/service-mgmt.go | 94 +++++++++++++++++++ go-apps/meep-app-enablement/server/routers.go | 7 ++ .../meep-subscriptions/subscription.go | 2 + 5 files changed, 123 insertions(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go index 8f1fca70e..e9e31a0ab 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go @@ -66,7 +66,9 @@ func ApplicationsSubscriptionsGET(w http.ResponseWriter, r *http.Request) { func ApplicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { applicationsSubscriptionsPOST(w, r) } - +func ApplicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { + applicationsSubscriptionsPUT(w, r) +} func ServicesGET(w http.ResponseWriter, r *http.Request) { servicesGET(w, r) } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go index 73bd9fc98..cd72190c9 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -87,6 +87,23 @@ func convertJsonToSerAvailabilityNotifSub(jsonData string) *SerAvailabilityNotif return &obj } +func convertEventFiltersToStrings(filters []CapifEventFilter) []string { + var stringFilters []string + for _, filter := range filters { + stringFilters = append(stringFilters, filter.ApiIds...) + } + return stringFilters +} + +func convertEventToStrings(events []CapifEvent) []string { + var stringEvents []string + if len(events) > 0 { + // Directly convert CapifEvent to string and append + stringEvents = append(stringEvents, string(events[0])) + } + return stringEvents +} + func convertJsonToSerAvailabilityNotifSub_1(jsonData string) *EventSubscription { var obj EventSubscription err := json.Unmarshal([]byte(jsonData), &obj) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 50f27bb62..eb6d0f93c 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -882,6 +882,92 @@ func servicesGET(w http.ResponseWriter, r *http.Request) { } } +func applicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { + log.Info("applicationsSubscriptionsPUT") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + subId := vars["subscriptionId"] + appId := vars["subscriberId"] + + 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 + } + sub, err := subMgr.GetSubscription(subId) + if err != nil { + log.Error("Subscription not found: ", err.Error()) + errHandlerProblemDetails(w, "Subscription not found", http.StatusNotFound) + return + } + // Retrieve the update request + if r.Body == nil { + err := errors.New("Request body is missing") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + var updatedSub EventSubscription + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&updatedSub) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, "Failed to decode request body", http.StatusInternalServerError) + return + } + if updatedSub.NotificationDestination == "" { + log.Error("Either NotificationDestination must be set") + errHandlerProblemDetails(w, "Either NotificationDestination must be set", http.StatusBadRequest) + return + } + // Update the subscription object + if updatedSub.NotificationDestination != "" { + sub.Cfg.NotifyUrl = updatedSub.NotificationDestination + } + if updatedSub.RequestTestNotification { + sub.Cfg.RequestTestNotif = true + } + // if updatedSub.RequestWebsocketUri { + // sub.Cfg.RequestWebsocketUri = true + // } else { + // sub.Cfg.RequestWebsocketUri = false + // } + // Update event filters if provided + if updatedSub.EventFilters != nil { + sub.Cfg.EventFilters = convertEventFiltersToStrings(updatedSub.EventFilters) + } + if updatedSub.Events != nil { + sub.Cfg.CapifEvent = convertEventToStrings(updatedSub.Events) + } + // Update the subscription in the manager + err = subMgr.UpdateSubscription(sub) + if err != nil { + log.Error("Failed to update subscription: ", err.Error()) + errHandlerProblemDetails(w, "Failed to update subscription", http.StatusInternalServerError) + return + } + jsonSub := convertSerAvailabilityNotifSubToJson_1(&updatedSub) + // Send success response + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, jsonSub) +} + func applicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { log.Info("applicationsSubscriptionsPOST") @@ -2040,6 +2126,12 @@ func newSerAvailabilityNotifSubCfg(sub *SerAvailabilityNotificationSubscription, } func newSerAvailabilityNotifSubCfg_1(sub *EventSubscription, subId string, appId string) *subs.SubscriptionCfg { + var eventFilters []string + for _, filter := range sub.EventFilters { + eventFilters = append(eventFilters, filter.ApiIds...) + } + var capifEvent []string + capifEvent = append(capifEvent, string(sub.Events[0])) subCfg := &subs.SubscriptionCfg{ Id: subId, AppId: appId, @@ -2050,6 +2142,8 @@ func newSerAvailabilityNotifSubCfg_1(sub *EventSubscription, subId string, appId PeriodicInterval: 0, RequestTestNotif: false, RequestWebsocketUri: false, + EventFilters: eventFilters, + CapifEvent: capifEvent, } return subCfg } diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 9ce35bb86..23926cef8 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -392,6 +392,13 @@ var routes = Routes{ capifMgmt.ApplicationsSubscriptionsPOST, }, + Route{ + "ApplicationsSubscriptionsPUT", + strings.ToUpper("Put"), + "/capif-events/v1/{subscriberId}/subscriptions/{subscriptionId} ", + capifMgmt.ApplicationsSubscriptionsPUT, + }, + Route{ "Index", "GET", diff --git a/go-packages/meep-subscriptions/subscription.go b/go-packages/meep-subscriptions/subscription.go index a679912af..d167455a9 100644 --- a/go-packages/meep-subscriptions/subscription.go +++ b/go-packages/meep-subscriptions/subscription.go @@ -40,6 +40,8 @@ type SubscriptionCfg struct { PeriodicInterval int32 `json:"periodicInterval"` RequestTestNotif bool `json:"reqTestNotif"` RequestWebsocketUri bool `json:"reqWebsockUri"` + EventFilters []string `json:"eventFilters"` + CapifEvent []string `json:"capifEvent"` } type Subscription struct { -- GitLab From aa336de5a2f8f6998cc625b6f66acc7a2219599f Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 4 Sep 2024 15:44:17 +0500 Subject: [PATCH 28/43] Fix URL in router.go file --- go-apps/meep-app-enablement/server/routers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 23926cef8..dcdc286e8 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -395,7 +395,7 @@ var routes = Routes{ Route{ "ApplicationsSubscriptionsPUT", strings.ToUpper("Put"), - "/capif-events/v1/{subscriberId}/subscriptions/{subscriptionId} ", + "/capif-events/v1/{subscriberId}/subscriptions/{subscriptionId}", capifMgmt.ApplicationsSubscriptionsPUT, }, -- GitLab From 12dc6d6fa9b8e018e1365697a346994477a2ef3b Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 5 Sep 2024 09:56:09 +0500 Subject: [PATCH 29/43] Fix issue in PUT method to update the CAPIF event subscription --- .../server/capif-mgmt/service-mgmt.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index eb6d0f93c..9eb71823a 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -940,21 +940,21 @@ func applicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { if updatedSub.NotificationDestination != "" { sub.Cfg.NotifyUrl = updatedSub.NotificationDestination } - if updatedSub.RequestTestNotification { - sub.Cfg.RequestTestNotif = true - } + // if updatedSub.RequestTestNotification { + // sub.Cfg.RequestTestNotif = true + // } // if updatedSub.RequestWebsocketUri { // sub.Cfg.RequestWebsocketUri = true // } else { // sub.Cfg.RequestWebsocketUri = false // } // Update event filters if provided - if updatedSub.EventFilters != nil { - sub.Cfg.EventFilters = convertEventFiltersToStrings(updatedSub.EventFilters) - } - if updatedSub.Events != nil { - sub.Cfg.CapifEvent = convertEventToStrings(updatedSub.Events) - } + // if updatedSub.EventFilters != nil { + // sub.Cfg.EventFilters = convertEventFiltersToStrings(updatedSub.EventFilters) + // } + // if updatedSub.Events != nil { + // sub.Cfg.CapifEvent = convertEventToStrings(updatedSub.Events) + // } // Update the subscription in the manager err = subMgr.UpdateSubscription(sub) if err != nil { -- GitLab From c28481f70a6a9df0c93af0abe3984abab3070dd6 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 5 Sep 2024 09:58:13 +0500 Subject: [PATCH 30/43] Add functionality to update the event filter and capif events in subscription --- .../server/capif-mgmt/service-mgmt.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 9eb71823a..267d4694c 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -949,12 +949,12 @@ func applicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { // sub.Cfg.RequestWebsocketUri = false // } // Update event filters if provided - // if updatedSub.EventFilters != nil { - // sub.Cfg.EventFilters = convertEventFiltersToStrings(updatedSub.EventFilters) - // } - // if updatedSub.Events != nil { - // sub.Cfg.CapifEvent = convertEventToStrings(updatedSub.Events) - // } + if updatedSub.EventFilters != nil { + sub.Cfg.EventFilters = convertEventFiltersToStrings(updatedSub.EventFilters) + } + if updatedSub.Events != nil { + sub.Cfg.CapifEvent = convertEventToStrings(updatedSub.Events) + } // Update the subscription in the manager err = subMgr.UpdateSubscription(sub) if err != nil { -- GitLab From c089660fc63040615d7a775af964c214eb7a6f0e Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 5 Sep 2024 11:19:13 +0500 Subject: [PATCH 31/43] Add DELETE method in CAPIF API to delete the event subscriptions by its ID --- .../meep-app-enablement/server/capif-mgmt/service-mgmt.go | 4 ++-- go-apps/meep-app-enablement/server/routers.go | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 267d4694c..af23f8ea5 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1119,7 +1119,7 @@ func applicationsSubscriptionDELETE(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) subId := vars["subscriptionId"] - appId := vars["appInstanceId"] + appId := vars["subscriberId"] mutex.Lock() defer mutex.Unlock() @@ -1153,7 +1153,7 @@ func applicationsSubscriptionDELETE(w http.ResponseWriter, r *http.Request) { } // Validate subscription - if sub.Cfg.AppId != appId || sub.Cfg.Type != SER_AVAILABILITY_NOTIF_SUB_TYPE { + if sub.Cfg.AppId != appId { err = errors.New("Subscription not found") log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index dcdc286e8..8f8ac2206 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -399,6 +399,13 @@ var routes = Routes{ capifMgmt.ApplicationsSubscriptionsPUT, }, + Route{ + "ApplicationsSubscriptionDELETE", + strings.ToUpper("Delete"), + "/capif-events/v1/{subscriberId}/subscriptions/{subscriptionId}", + svcMgmt.ApplicationsSubscriptionDELETE, + }, + Route{ "Index", "GET", -- GitLab From a0302078e5d57b3ba8e8bb9f2875a3a3ad8f9465 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 5 Sep 2024 11:42:44 +0500 Subject: [PATCH 32/43] Fix isuue in router.go file related to Delete subscription endpoint --- go-apps/meep-app-enablement/server/routers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 8f8ac2206..6bc61bc6d 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -403,7 +403,7 @@ var routes = Routes{ "ApplicationsSubscriptionDELETE", strings.ToUpper("Delete"), "/capif-events/v1/{subscriberId}/subscriptions/{subscriptionId}", - svcMgmt.ApplicationsSubscriptionDELETE, + capifMgmt.ApplicationsSubscriptionDELETE, }, Route{ -- GitLab From d4d4f07497da59fa4d61d5a91de070f878cfe1f0 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Fri, 6 Sep 2024 12:54:16 +0500 Subject: [PATCH 33/43] Add patch method in CAPIF API to update the event subsription --- .../server/capif-mgmt/api_mec_service_mgmt.go | 5 + .../server/capif-mgmt/convert.go | 20 ++++ .../model_event_subscription_patch.go | 18 +++ .../server/capif-mgmt/service-mgmt.go | 107 +++++++++++++++++- go-apps/meep-app-enablement/server/routers.go | 7 ++ 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription_patch.go diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go index e9e31a0ab..95e58c21c 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/api_mec_service_mgmt.go @@ -69,6 +69,11 @@ func ApplicationsSubscriptionsPOST(w http.ResponseWriter, r *http.Request) { func ApplicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { applicationsSubscriptionsPUT(w, r) } + +func ApplicationsSubscriptionsPATCH(w http.ResponseWriter, r *http.Request) { + applicationsSubscriptionsPATCH(w, r) +} + func ServicesGET(w http.ResponseWriter, r *http.Request) { servicesGET(w, r) } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go index cd72190c9..fb49112e5 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/convert.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/convert.go @@ -87,6 +87,26 @@ func convertJsonToSerAvailabilityNotifSub(jsonData string) *SerAvailabilityNotif return &obj } +// Convert []string back to []CapifEventFilter +func convertStringsToEventFilters(stringFilters []string) []CapifEventFilter { + var eventFilters []CapifEventFilter + for _, filter := range stringFilters { + eventFilters = append(eventFilters, CapifEventFilter{ + ApiIds: []string{filter}, // Assuming each string corresponds to an ApiId in the CapifEventFilter + }) + } + return eventFilters +} + +// Convert []string back to []CapifEvent +func convertStringsToEvents(stringEvents []string) []CapifEvent { + var events []CapifEvent + for _, event := range stringEvents { + events = append(events, CapifEvent(event)) // Assuming the string directly maps to CapifEvent + } + return events +} + func convertEventFiltersToStrings(filters []CapifEventFilter) []string { var stringFilters []string for _, filter := range filters { diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription_patch.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription_patch.go new file mode 100644 index 000000000..7591b2aea --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_event_subscription_patch.go @@ -0,0 +1,18 @@ +/* + * 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 EventSubscriptionPatch struct { + // The events for which the subscription is modified. + Events []CapifEvent `json:"events"` + EventFilters []CapifEventFilter `json:"eventFilters,omitempty"` + // URI to which notifications will be sent. Shall be set to the value of the \"callbackReference\" attribute in the \"SerAvailabilityNotificationSubscription\" structure. + NotificationDestination string `json:"notificationDestination,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index af23f8ea5..183c7b06b 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -882,6 +882,96 @@ func servicesGET(w http.ResponseWriter, r *http.Request) { } } +func applicationsSubscriptionsPATCH(w http.ResponseWriter, r *http.Request) { + log.Info("applicationsSubscriptionsPATCH") + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + vars := mux.Vars(r) + subId := vars["subscriptionId"] + appId := vars["subscriberId"] + + 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 + } + + // Retrieve the existing subscription + sub, err := subMgr.GetSubscription(subId) + if err != nil { + log.Error("Subscription not found: ", err.Error()) + errHandlerProblemDetails(w, "Subscription not found", http.StatusNotFound) + return + } + + // Retrieve the patch request body + if r.Body == nil { + err := errors.New("Request body is missing") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + + var patchSub EventSubscriptionPatch + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&patchSub) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, "Failed to decode request body", http.StatusInternalServerError) + return + } + + // Apply partial updates + if patchSub.NotificationDestination != "" { + sub.Cfg.NotifyUrl = patchSub.NotificationDestination + } + + if patchSub.EventFilters != nil { + sub.Cfg.EventFilters = convertEventFiltersToStrings(patchSub.EventFilters) + } + + if patchSub.Events != nil { + sub.Cfg.CapifEvent = convertEventToStrings(patchSub.Events) + } + + // Update the subscription in the manager + err = subMgr.UpdateSubscription(sub) + if err != nil { + log.Error("Failed to update subscription: ", err.Error()) + errHandlerProblemDetails(w, "Failed to update subscription", http.StatusInternalServerError) + return + } + + // Convert the updated subscription to an EventSubscription struct + updatedSub := EventSubscription{ + NotificationDestination: sub.Cfg.NotifyUrl, + EventFilters: convertStringsToEventFilters(sub.Cfg.EventFilters), + Events: convertStringsToEvents(sub.Cfg.CapifEvent), + } + + // Convert the updated EventSubscription to JSON format for the response + jsonSub := convertSerAvailabilityNotifSubToJson_1(&updatedSub) + + // Send the full updated subscription in the response + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, jsonSub) +} + func applicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { log.Info("applicationsSubscriptionsPUT") w.Header().Set("Content-Type", "application/json; charset=UTF-8") @@ -932,8 +1022,21 @@ func applicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { return } if updatedSub.NotificationDestination == "" { - log.Error("Either NotificationDestination must be set") - errHandlerProblemDetails(w, "Either NotificationDestination must be set", http.StatusBadRequest) + log.Error("NotificationDestination is required for PUT") + errHandlerProblemDetails(w, "NotificationDestination is required", http.StatusBadRequest) + return + } + + // Assume `EventFilters` and `Events` are mandatory for `PUT` as well + if updatedSub.EventFilters == nil || len(updatedSub.EventFilters) == 0 { + log.Error("EventFilters are required for PUT") + errHandlerProblemDetails(w, "EventFilters are required", http.StatusBadRequest) + return + } + + if updatedSub.Events == nil || len(updatedSub.Events) == 0 { + log.Error("Events are required for PUT") + errHandlerProblemDetails(w, "Events are required", http.StatusBadRequest) return } // Update the subscription object diff --git a/go-apps/meep-app-enablement/server/routers.go b/go-apps/meep-app-enablement/server/routers.go index 6bc61bc6d..1ad8f96b9 100644 --- a/go-apps/meep-app-enablement/server/routers.go +++ b/go-apps/meep-app-enablement/server/routers.go @@ -399,6 +399,13 @@ var routes = Routes{ capifMgmt.ApplicationsSubscriptionsPUT, }, + Route{ + "ApplicationsSubscriptionsPATCH", + strings.ToUpper("Patch"), + "/capif-events/v1/{subscriberId}/subscriptions/{subscriptionId}", + capifMgmt.ApplicationsSubscriptionsPATCH, + }, + Route{ "ApplicationsSubscriptionDELETE", strings.ToUpper("Delete"), -- GitLab From eb357ba0864fd70316bf6358d5da5d6a483a90e0 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 15 Oct 2024 13:33:45 +0500 Subject: [PATCH 34/43] Fix PATCH method of resource Published API --- .../server/capif-mgmt/service-mgmt.go | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 183c7b06b..41ce53db8 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -717,9 +717,53 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { } // else, nothing to do _sInfo.LivenessInterval = sInfoPrev.LivenessInterval - // Send response + // Map ServiceInfoList to ServiceApiDescription list + serviceApiDescriptions := make([]ServiceApiDescription, 0) + + // Assuming _sInfo is an instance of ServiceInfo + service := _sInfo + + // Create an AefProfile from TransportInfo inside ServiceInfo + aefProfile := AefProfile{ + AefId: service.TransportInfo.Id, + Versions: []string{service.Version}, // Assuming Version is a string + InterfaceDescriptions: service.TransportInfo.Endpoint, + VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ + Name: service.TransportInfo.Name, + Type_: service.TransportInfo.Type_, + Protocol: service.TransportInfo.Protocol, + Version: service.TransportInfo.Version, + Security: service.TransportInfo.Security, + }, + } + + // Create the ServiceApiDescription and populate it with data from ServiceInfo + apiDesc := ServiceApiDescription{ + ApiName: service.SerName, // Map SerName to ApiName + ApiId: service.SerInstanceId, // Map SerInstanceId to ApiId + AefProfiles: []AefProfile{aefProfile}, + VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ + Serializer: service.Serializer, + State: service.State, + ScopeOfLocality: service.ScopeOfLocality, + ConsumedLocalOnly: service.ConsumedLocalOnly, + IsLocal: service.IsLocal, + Category: service.SerCategory, + }, + } + + // Add the created apiDesc to the serviceApiDescriptions slice + serviceApiDescriptions = append(serviceApiDescriptions, apiDesc) + + // Prepare & send response + jsonResponse, err := json.Marshal(serviceApiDescriptions) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } w.WriteHeader(http.StatusOK) - fmt.Fprint(w, convertServiceInfoToJson_2(dsInfo)) + fmt.Fprint(w, string(jsonResponse)) } func appServicesByIdDELETE(w http.ResponseWriter, r *http.Request) { -- GitLab From 9734adeb6c3292ab826b7e05ad34355491b06c95 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 16 Oct 2024 11:47:34 +0500 Subject: [PATCH 35/43] Add aefProfile attribute functionality in serviceApiDescriptionPatch data model --- .../model_service_api_description_patch.go | 1 + .../server/capif-mgmt/service-mgmt.go | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go index cf0cf27f0..246fc0146 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_service_api_description_patch.go @@ -10,5 +10,6 @@ package server type ServiceApiDescriptionPatch struct { + AefProfiles []AefProfile `json:"aefProfiles,omitempty"` VendorSpecificUrnetsimeccapifextserviceInfo *MecServiceInfoCapifExtPatch `json:"vendorSpecific-urn:etsi:mec:capifext:service-info,omitempty"` } diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 41ce53db8..5dee082c4 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -638,8 +638,20 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { 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{ + AefProfiles: []AefProfile{*aefProfile}, VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExtPatch{ Serializer: sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, State: sInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State, @@ -649,7 +661,15 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { 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{ SerInstanceId: sInfoPrev.SerInstanceId, @@ -657,7 +677,7 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { Version: sInfoPrev.Version, SerCategory: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category, State: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State, - TransportInfo: sInfoPrev.TransportInfo, + TransportInfo: &transportInfo_, Serializer: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Serializer, ScopeOfLocality: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ScopeOfLocality, ConsumedLocalOnly: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.ConsumedLocalOnly, @@ -724,7 +744,7 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { service := _sInfo // Create an AefProfile from TransportInfo inside ServiceInfo - aefProfile := AefProfile{ + aefProfile_ := AefProfile{ AefId: service.TransportInfo.Id, Versions: []string{service.Version}, // Assuming Version is a string InterfaceDescriptions: service.TransportInfo.Endpoint, @@ -741,7 +761,7 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { apiDesc := ServiceApiDescription{ ApiName: service.SerName, // Map SerName to ApiName ApiId: service.SerInstanceId, // Map SerInstanceId to ApiId - AefProfiles: []AefProfile{aefProfile}, + AefProfiles: []AefProfile{aefProfile_}, VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ Serializer: service.Serializer, State: service.State, -- GitLab From d341c6420475df0fc5404638e71d6b03a0d9828a Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 16 Oct 2024 12:30:18 +0500 Subject: [PATCH 36/43] Fix minor issue in PATCH method of published API resource --- .../server/capif-mgmt/service-mgmt.go | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 5dee082c4..2e7bcd6e3 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -744,24 +744,24 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { service := _sInfo // Create an AefProfile from TransportInfo inside ServiceInfo - aefProfile_ := AefProfile{ - AefId: service.TransportInfo.Id, - Versions: []string{service.Version}, // Assuming Version is a string - InterfaceDescriptions: service.TransportInfo.Endpoint, - VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ - Name: service.TransportInfo.Name, - Type_: service.TransportInfo.Type_, - Protocol: service.TransportInfo.Protocol, - Version: service.TransportInfo.Version, - Security: service.TransportInfo.Security, - }, - } + // aefProfile_ := AefProfile{ + // AefId: service.TransportInfo.Id, + // Versions: []string{service.Version}, // Assuming Version is a string + // InterfaceDescriptions: service.TransportInfo.Endpoint, + // VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ + // Name: service.TransportInfo.Name, + // Type_: service.TransportInfo.Type_, + // Protocol: service.TransportInfo.Protocol, + // Version: service.TransportInfo.Version, + // Security: service.TransportInfo.Security, + // }, + // } // Create the ServiceApiDescription and populate it with data from ServiceInfo apiDesc := ServiceApiDescription{ ApiName: service.SerName, // Map SerName to ApiName ApiId: service.SerInstanceId, // Map SerInstanceId to ApiId - AefProfiles: []AefProfile{aefProfile_}, + AefProfiles: dsInfo.AefProfiles, VendorSpecificUrnetsimeccapifextserviceInfo: &MecServiceInfoCapifExt{ Serializer: service.Serializer, State: service.State, -- GitLab From 20ba6353e52b41a6dd2354b506af65c45629e24f Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 16 Oct 2024 13:20:13 +0500 Subject: [PATCH 37/43] Fix minor issue in AefProfile data model --- go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 2e7bcd6e3..5f20797f1 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -674,7 +674,7 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { _sInfo := ServiceInfo{ SerInstanceId: sInfoPrev.SerInstanceId, SerName: sInfoPrev.SerName, - Version: sInfoPrev.Version, + Version: dsInfo.AefProfiles[0].Versions[0], SerCategory: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.Category, State: dsInfo.VendorSpecificUrnetsimeccapifextserviceInfo.State, TransportInfo: &transportInfo_, -- GitLab From 29cdfe1c6a2a7e6e45285e455e5f92e9eb856734 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Tue, 22 Oct 2024 11:14:59 +0500 Subject: [PATCH 38/43] Store service API descriptions in DiscoveredAPIs struct and send response. --- .../server/capif-mgmt/model_discover_api.go | 19 +++++++++++++++++++ .../server/capif-mgmt/service-mgmt.go | 7 +++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 go-apps/meep-app-enablement/server/capif-mgmt/model_discover_api.go diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/model_discover_api.go b/go-apps/meep-app-enablement/server/capif-mgmt/model_discover_api.go new file mode 100644 index 000000000..e728f6ee4 --- /dev/null +++ b/go-apps/meep-app-enablement/server/capif-mgmt/model_discover_api.go @@ -0,0 +1,19 @@ +/* + * 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 + +// DiscoveredAPIs represents the structure for discovered APIs +type DiscoveredAPIs struct { + // ServiceAPIDescriptions is an optional array of service API descriptions as published by the service. + // NOTE: For the CAPIF_Discover_Service_API, the supportedFeatures attribute of the ServiceAPIDescription data type + // shall be provided in the HTTP GET response of a successful query. + // Additionally, supportedFeatures may include one or more supported features as defined in clause 8.1.6. + ServiceAPIDescriptions []ServiceApiDescription `json:"serviceAPIDescriptions,omitempty"` +} diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 5f20797f1..4a1692335 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -1825,9 +1825,12 @@ func getServices(w http.ResponseWriter, r *http.Request, appId string) { } serviceApiDescriptions = append(serviceApiDescriptions, apiDesc) } - + // Store the response in the DiscoveredAPIs struct + discoveredAPIs := DiscoveredAPIs{ + ServiceAPIDescriptions: serviceApiDescriptions, + } // Prepare & send response - jsonResponse, err := json.Marshal(serviceApiDescriptions) + jsonResponse, err := json.Marshal(discoveredAPIs) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) -- GitLab From 1aafa095d6f2e0ca14b2feffaf884579200a015d Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Thu, 24 Oct 2024 09:25:29 +0500 Subject: [PATCH 39/43] Clean the code --- .../server/capif-mgmt/service-mgmt.go | 30 +------------------ 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index 4a1692335..afc2fd35a 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -521,7 +521,6 @@ func appServicesByIdPUT(w http.ResponseWriter, r *http.Request) { } // 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; @@ -686,11 +685,6 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { } // 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 @@ -740,23 +734,8 @@ func appServicesByIdPATCH(w http.ResponseWriter, r *http.Request) { // Map ServiceInfoList to ServiceApiDescription list serviceApiDescriptions := make([]ServiceApiDescription, 0) - // Assuming _sInfo is an instance of ServiceInfo service := _sInfo - // Create an AefProfile from TransportInfo inside ServiceInfo - // aefProfile_ := AefProfile{ - // AefId: service.TransportInfo.Id, - // Versions: []string{service.Version}, // Assuming Version is a string - // InterfaceDescriptions: service.TransportInfo.Endpoint, - // VendorSpecificUrnetsimeccapifexttransportInfo: &MecTransportInfoCapifExt{ - // Name: service.TransportInfo.Name, - // Type_: service.TransportInfo.Type_, - // Protocol: service.TransportInfo.Protocol, - // Version: service.TransportInfo.Version, - // Security: service.TransportInfo.Security, - // }, - // } - // Create the ServiceApiDescription and populate it with data from ServiceInfo apiDesc := ServiceApiDescription{ ApiName: service.SerName, // Map SerName to ApiName @@ -1107,14 +1086,7 @@ func applicationsSubscriptionsPUT(w http.ResponseWriter, r *http.Request) { if updatedSub.NotificationDestination != "" { sub.Cfg.NotifyUrl = updatedSub.NotificationDestination } - // if updatedSub.RequestTestNotification { - // sub.Cfg.RequestTestNotif = true - // } - // if updatedSub.RequestWebsocketUri { - // sub.Cfg.RequestWebsocketUri = true - // } else { - // sub.Cfg.RequestWebsocketUri = false - // } + // Update event filters if provided if updatedSub.EventFilters != nil { sub.Cfg.EventFilters = convertEventFiltersToStrings(updatedSub.EventFilters) -- GitLab From 31b3e21990b49804451a881cd850745ca7b28ec3 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Mon, 28 Oct 2024 10:02:21 +0500 Subject: [PATCH 40/43] Add appProfile attribute functionality in registration endpoint --- .../server/app-support/app-support.go | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/go-apps/meep-app-enablement/server/app-support/app-support.go b/go-apps/meep-app-enablement/server/app-support/app-support.go index a743ad807..a79558356 100644 --- a/go-apps/meep-app-enablement/server/app-support/app-support.go +++ b/go-apps/meep-app-enablement/server/app-support/app-support.go @@ -22,6 +22,7 @@ import ( "fmt" "net/http" "net/url" + "reflect" "strconv" "sync" "time" @@ -686,6 +687,25 @@ func appRegistrationPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, "Endpoint shall be present when IsInsByMec is FALSE.", http.StatusBadRequest) return } + // Process appProfile if present + if appInfo.AppProfile != nil { + // Validate appProvider, endpoint, and other fields as per mapping to EASProfile + if appInfo.AppProvider != appInfo.AppProfile.ProvId { + log.Error("appProvider in AppInfo does not match provId in appProfile") + errHandlerProblemDetails(w, "appProvider and provId must be consistent", http.StatusBadRequest) + return + } + + if appInfo.AppProfile != nil { + if !reflect.DeepEqual(getEndpointUris(appInfo.Endpoint), getProfileEndpointUris(appInfo.AppProfile.EndPt)) { + log.Error("endpoint in AppInfo does not match endPt in appProfile") + errHandlerProblemDetails(w, "Endpoint and endPt must be consistent", http.StatusBadRequest) + return + } + } + + // Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes + } // Get App instance log.Info("appRegistrationPOST: appInfo.AppInstanceId: ", appInfo.AppInstanceId) @@ -731,6 +751,24 @@ func appRegistrationPOST(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, jsonResponse) } +func getEndpointUris(endpoint *OneOfAppInfoEndpoint) []string { + if endpoint == nil { + return nil + } + + // Access the `Uris` field directly from `EndPointInfoUris` + return endpoint.EndPointInfoUris.Uris +} + +func getProfileEndpointUris(endPt *OneOfAppProfileEndPt) []string { + if endPt == nil { + return nil + } + + // Access the `Uris` field directly from `EndPointInfoUris` + return endPt.EndPointInfoUris.Uris +} + /* * appRegistrationGET handles retrieving the registration information of an application. * It fetches the appInstanceId from the URL variables, retrieves the associated application info from Redis, and sends it back in the response. If the appInstanceId is not found or an error occurs, it responds with the appropriate status and error message. -- GitLab From cce416a9fc447d132ca02822aef4c487188a3fd8 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Mon, 28 Oct 2024 12:09:44 +0500 Subject: [PATCH 41/43] Add appProfile attributes functionality in PUT method --- .../server/app-support/app-support.go | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/go-apps/meep-app-enablement/server/app-support/app-support.go b/go-apps/meep-app-enablement/server/app-support/app-support.go index a79558356..1e1e897df 100644 --- a/go-apps/meep-app-enablement/server/app-support/app-support.go +++ b/go-apps/meep-app-enablement/server/app-support/app-support.go @@ -704,6 +704,17 @@ func appRegistrationPOST(w http.ResponseWriter, r *http.Request) { } } + if appInfo.AppProfile.EasId == "" { + log.Error("Mandatory easId parameter should be present") + errHandlerProblemDetails(w, "Mandatory attribute easId is missing in the request body.", http.StatusBadRequest) + return + } + + if appInfo.AppName != appInfo.AppProfile.EasId { + log.Error("AppName in AppInfo does not match EasId in appProfile") + errHandlerProblemDetails(w, "AppName and EasId must be consistent", http.StatusBadRequest) + return + } // Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes } @@ -870,6 +881,34 @@ func appRegistrationPUT(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, "Shall be present when IsInsByMec is FALSE.", http.StatusBadRequest) return } + // Process appProfile if present + if appInfoPut.AppProfile != nil { + // Validate appProvider, endpoint, and other fields as per mapping to EASProfile + if appInfoPut.AppProvider != appInfoPut.AppProfile.ProvId { + log.Error("appProvider in AppInfo does not match provId in appProfile") + errHandlerProblemDetails(w, "appProvider and provId must be consistent", http.StatusBadRequest) + return + } + + if appInfoPut.AppProfile != nil { + if !reflect.DeepEqual(getEndpointUris(appInfoPut.Endpoint), getProfileEndpointUris(appInfoPut.AppProfile.EndPt)) { + log.Error("endpoint in AppInfo does not match endPt in appProfile") + errHandlerProblemDetails(w, "Endpoint and endPt must be consistent", http.StatusBadRequest) + return + } + } + if appInfoPut.AppProfile.EasId == "" { + log.Error("Mandatory easId parameter should be present") + errHandlerProblemDetails(w, "Mandatory attribute easId is missing in the request body.", http.StatusBadRequest) + return + } + if appInfoPut.AppName != appInfoPut.AppProfile.EasId { + log.Error("AppName in AppInfo does not match EasId in appProfile") + errHandlerProblemDetails(w, "AppName and EasId must be consistent", http.StatusBadRequest) + return + } + // Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes + } appInfoPut.AppInstanceId = appInstanceId -- GitLab From f3cc21ea935cdebbb5e49422a449cb10049027e4 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 30 Oct 2024 12:45:16 +0500 Subject: [PATCH 42/43] Refactor appRegistrationPOST and appRegistrationPUT for improved readability, consistency, and error handling. --- .../server/app-support/app-support.go | 174 +++++++++--------- 1 file changed, 86 insertions(+), 88 deletions(-) diff --git a/go-apps/meep-app-enablement/server/app-support/app-support.go b/go-apps/meep-app-enablement/server/app-support/app-support.go index 1e1e897df..e4f2ca46d 100644 --- a/go-apps/meep-app-enablement/server/app-support/app-support.go +++ b/go-apps/meep-app-enablement/server/app-support/app-support.go @@ -655,109 +655,106 @@ func timingCurrentTimeGET(w http.ResponseWriter, r *http.Request) { * @return {error} error An error will return if occurs */ func appRegistrationPOST(w http.ResponseWriter, r *http.Request) { - log.Debug(">>> appRegistrationPOST: ", r) + log.Debug(">>> appRegistrationPOST:", r) w.Header().Set("Content-Type", "application/json; charset=UTF-8") - // Decode the request body into AppInfo struct + // Parse request body into AppInfo struct var appInfo AppInfo - err := json.NewDecoder(r.Body).Decode(&appInfo) - if err != nil { - log.Error(err.Error()) - errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + if err := json.NewDecoder(r.Body).Decode(&appInfo); err != nil { + log.Error("Error decoding request body:", err) + errHandlerProblemDetails(w, "Invalid request body.", http.StatusBadRequest) return } - log.Info("appRegistrationPOST: appInfo: ", appInfo) + log.Info("appRegistrationPOST: Received appInfo:", appInfo) - // Validation of mandatory parameters + // Validate required fields if appInfo.AppName == "" { - log.Error("Mandatory AppName parameter not present") - errHandlerProblemDetails(w, "Mandatory AppName parameter not present", http.StatusBadRequest) + log.Error("Missing mandatory parameter: AppName") + errHandlerProblemDetails(w, "Mandatory attribute AppName is missing.", http.StatusBadRequest) return } if appInfo.AppInstanceId == "" { - log.Error("Mandatory appInstanceId parameter should be present") - errHandlerProblemDetails(w, "Mandatory attribute appInstanceId is missing in the request body.", http.StatusBadRequest) + log.Error("Missing mandatory parameter: AppInstanceId") + errHandlerProblemDetails(w, "Mandatory attribute AppInstanceId is missing.", http.StatusBadRequest) return } if !appInfo.IsInsByMec && appInfo.Endpoint == nil { - log.Error("Shall be present when IsInsByMec is FALSE") - errHandlerProblemDetails(w, "Endpoint shall be present when IsInsByMec is FALSE.", http.StatusBadRequest) + log.Error("Endpoint is required when IsInsByMec is FALSE") + errHandlerProblemDetails(w, "Endpoint is required when IsInsByMec is FALSE.", http.StatusBadRequest) return } - // Process appProfile if present + + // Process appProfile if provided if appInfo.AppProfile != nil { - // Validate appProvider, endpoint, and other fields as per mapping to EASProfile + // Validate appProvider and other fields mapped to EASProfile if appInfo.AppProvider != appInfo.AppProfile.ProvId { - log.Error("appProvider in AppInfo does not match provId in appProfile") - errHandlerProblemDetails(w, "appProvider and provId must be consistent", http.StatusBadRequest) + log.Error("Mismatch between appProvider in AppInfo and provId in appProfile") + errHandlerProblemDetails(w, "appProvider and provId must match.", http.StatusBadRequest) return } - if appInfo.AppProfile != nil { - if !reflect.DeepEqual(getEndpointUris(appInfo.Endpoint), getProfileEndpointUris(appInfo.AppProfile.EndPt)) { - log.Error("endpoint in AppInfo does not match endPt in appProfile") - errHandlerProblemDetails(w, "Endpoint and endPt must be consistent", http.StatusBadRequest) - return - } + if !reflect.DeepEqual(getEndpointUris(appInfo.Endpoint), getProfileEndpointUris(appInfo.AppProfile.EndPt)) { + log.Error("Mismatch between endpoint in AppInfo and endPt in appProfile") + errHandlerProblemDetails(w, "Endpoint and endPt must match.", http.StatusBadRequest) + return } if appInfo.AppProfile.EasId == "" { - log.Error("Mandatory easId parameter should be present") - errHandlerProblemDetails(w, "Mandatory attribute easId is missing in the request body.", http.StatusBadRequest) + log.Error("Missing mandatory parameter: easId") + errHandlerProblemDetails(w, "Mandatory attribute easId is missing.", http.StatusBadRequest) return } if appInfo.AppName != appInfo.AppProfile.EasId { - log.Error("AppName in AppInfo does not match EasId in appProfile") - errHandlerProblemDetails(w, "AppName and EasId must be consistent", http.StatusBadRequest) + log.Error("Mismatch between AppName in AppInfo and EasId in appProfile") + errHandlerProblemDetails(w, "AppName and EasId must match.", http.StatusBadRequest) return } - // Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes + // Additional checks for attributes such as scheds, svcArea, etc., as required. } - // Get App instance - log.Info("appRegistrationPOST: appInfo.AppInstanceId: ", appInfo.AppInstanceId) + // Retrieve App instance information + log.Info("appRegistrationPOST: Processing AppInstanceId:", appInfo.AppInstanceId) appId, err := getAppInfo(appInfo.AppInstanceId) if err != nil { - log.Error(err.Error()) - errHandlerProblemDetails(w, err.Error(), http.StatusNotFound) + log.Error("Error retrieving app instance:", err) + errHandlerProblemDetails(w, "App instance not found.", http.StatusNotFound) return } - log.Info("appRegistrationPOST: appId: ", appId) + log.Info("appRegistrationPOST: Retrieved appId:", appId) - // Validate App info + // Validate the retrieved AppInfo code, problemDetails, err := validateAppInfo(appId) if err != nil { - log.Error(err.Error()) + log.Error("Error validating app info:", err) if problemDetails != "" { w.WriteHeader(code) fmt.Fprint(w, problemDetails) } else { - errHandlerProblemDetails(w, err.Error(), code) + errHandlerProblemDetails(w, "Validation error.", code) } return } - // Set the application info in Redis + // Store AppInfo in Redis keyName := baseKey + "appInfo:" + appInfo.AppInstanceId - log.Info("appRegistrationPOST: keyName: ", keyName) + log.Info("appRegistrationPOST: Storing data with key:", keyName) if err := rc.JSONSetEntry(keyName, ".", convertAppInfoToJson(&appInfo)); err != nil { - log.Error("Unable to store new Registration in redis") - errHandlerProblemDetails(w, "Unable to store new Registration in redis", http.StatusInternalServerError) + log.Error("Failed to store registration in Redis:", err) + errHandlerProblemDetails(w, "Server error. Could not store registration.", http.StatusInternalServerError) return } - // Create a unique link for every subscription and concatenate subscription to it + // Generate resource URI for the created app registration resourceURI := hostUrl.String() + basePath + "registrations/" + appInfo.AppInstanceId - log.Info("appRegistrationPOST: resourceUDI: ", resourceURI) + log.Info("appRegistrationPOST: Generated resource URI:", resourceURI) w.Header().Set("Location", resourceURI) - // Prepare & send response + // Send JSON response with status 201 Created jsonResponse := convertAppInfoToJson(&appInfo) - // On successful registration, return 201 Created with the response body w.WriteHeader(http.StatusCreated) fmt.Fprint(w, jsonResponse) } @@ -834,90 +831,91 @@ func appRegistrationGET(w http.ResponseWriter, r *http.Request) { * @return {error} error An error will return if occurs */ func appRegistrationPUT(w http.ResponseWriter, r *http.Request) { - log.Debug(">>> appRegistrationPUT: ", r) + log.Debug(">>> appRegistrationPUT:", r) w.Header().Set("Content-Type", "application/json; charset=UTF-8") vars := mux.Vars(r) appInstanceId := vars["appInstanceId"] - log.Info("appRegistrationPUT: appInstanceId: ", appInstanceId) + log.Info("appRegistrationPUT: Received appInstanceId:", appInstanceId) - // Read JSON input stream provided in the Request, and stores it in the buffer of a Decoder object - decoder := json.NewDecoder(r.Body) - // Decode function return strings containing the text provided in the request body + // Decode JSON input from request body into AppInfo structure var appInfoPut AppInfo - err := decoder.Decode(&appInfoPut) - if err != nil { - log.Error(err.Error()) - errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + if err := json.NewDecoder(r.Body).Decode(&appInfoPut); err != nil { + log.Error("Error decoding request body:", err) + errHandlerProblemDetails(w, "Invalid request body.", http.StatusBadRequest) return } - log.Info("appRegistrationPUT: appInfoPut: ", appInfoPut) + log.Info("appRegistrationPUT: Parsed appInfoPut:", appInfoPut) + // Check if the appInfo exists in Redis for the given appInstanceId keyName := baseKey + "appInfo:" + appInstanceId - log.Info("appRegistrationPUT: keyName: ", keyName) + log.Info("appRegistrationPUT: Checking existence of key:", keyName) jsonAppInfo, _ := rc.JSONGetEntry(keyName, ".") if jsonAppInfo == "" { - log.Error("appInfo not found against the provided appInstanceId") - errHandlerProblemDetails(w, "appInfo not found against the provided appInstanceId", http.StatusNotFound) + log.Error("No appInfo found for provided appInstanceId") + errHandlerProblemDetails(w, "appInfo not found for the provided appInstanceId", http.StatusNotFound) return } - if appInfoPut.AppInstanceId != "" { - if appInstanceId != appInfoPut.AppInstanceId { - log.Error("appInstnaceId provided in endpoint and in request body not matching") - errHandlerProblemDetails(w, "appInstanceId provided in endpoint and in request body not matching", http.StatusNotFound) - return - } + // Validate appInstanceId consistency between URL and request body + if appInfoPut.AppInstanceId != "" && appInstanceId != appInfoPut.AppInstanceId { + log.Error("appInstanceId mismatch between endpoint and request body") + errHandlerProblemDetails(w, "appInstanceId in endpoint and request body do not match", http.StatusBadRequest) + return } + // Validate required parameters if appInfoPut.AppName == "" { - log.Error("Mandatory AppName parameter not present") - errHandlerProblemDetails(w, "Mandatory AppName parameter not present", http.StatusBadRequest) + log.Error("Missing mandatory parameter: AppName") + errHandlerProblemDetails(w, "Mandatory attribute AppName is missing.", http.StatusBadRequest) return } if !appInfoPut.IsInsByMec && appInfoPut.Endpoint == nil { - log.Error("Shall be present when IsInsByMec is FALSE") - errHandlerProblemDetails(w, "Shall be present when IsInsByMec is FALSE.", http.StatusBadRequest) + log.Error("Endpoint is required when IsInsByMec is FALSE") + errHandlerProblemDetails(w, "Endpoint is required when IsInsByMec is FALSE.", http.StatusBadRequest) return } - // Process appProfile if present + + // Process appProfile if provided if appInfoPut.AppProfile != nil { - // Validate appProvider, endpoint, and other fields as per mapping to EASProfile + // Validate appProvider and associated fields as per EASProfile mapping if appInfoPut.AppProvider != appInfoPut.AppProfile.ProvId { - log.Error("appProvider in AppInfo does not match provId in appProfile") - errHandlerProblemDetails(w, "appProvider and provId must be consistent", http.StatusBadRequest) + log.Error("Mismatch between appProvider in AppInfo and provId in appProfile") + errHandlerProblemDetails(w, "appProvider and provId must match.", http.StatusBadRequest) return } - if appInfoPut.AppProfile != nil { - if !reflect.DeepEqual(getEndpointUris(appInfoPut.Endpoint), getProfileEndpointUris(appInfoPut.AppProfile.EndPt)) { - log.Error("endpoint in AppInfo does not match endPt in appProfile") - errHandlerProblemDetails(w, "Endpoint and endPt must be consistent", http.StatusBadRequest) - return - } + if !reflect.DeepEqual(getEndpointUris(appInfoPut.Endpoint), getProfileEndpointUris(appInfoPut.AppProfile.EndPt)) { + log.Error("Mismatch between endpoint in AppInfo and endPt in appProfile") + errHandlerProblemDetails(w, "Endpoint and endPt must match.", http.StatusBadRequest) + return } + if appInfoPut.AppProfile.EasId == "" { - log.Error("Mandatory easId parameter should be present") - errHandlerProblemDetails(w, "Mandatory attribute easId is missing in the request body.", http.StatusBadRequest) + log.Error("Missing mandatory parameter: easId") + errHandlerProblemDetails(w, "Mandatory attribute easId is missing.", http.StatusBadRequest) return } + if appInfoPut.AppName != appInfoPut.AppProfile.EasId { - log.Error("AppName in AppInfo does not match EasId in appProfile") - errHandlerProblemDetails(w, "AppName and EasId must be consistent", http.StatusBadRequest) + log.Error("Mismatch between AppName in AppInfo and EasId in appProfile") + errHandlerProblemDetails(w, "AppName and EasId must match.", http.StatusBadRequest) return } - // Additional consistency checks for fields like scheds, svcArea, etc., based on appProfile attributes + // Additional consistency checks for fields such as scheds, svcArea, etc., as required. } + // Set appInstanceId in appInfoPut and store in Redis appInfoPut.AppInstanceId = appInstanceId - - // Store appInfo key in redis - err = rc.JSONSetEntry(baseKey+"appInfo:"+appInstanceId, ".", convertAppInfoToJson(&appInfoPut)) - if err != nil { - log.Error("Failed to store AppInfo in the redis DB: ", err) + log.Info("appRegistrationPUT: Storing updated appInfo for appInstanceId:", appInstanceId) + if err := rc.JSONSetEntry(keyName, ".", convertAppInfoToJson(&appInfoPut)); err != nil { + log.Error("Failed to store updated AppInfo in Redis:", err) + errHandlerProblemDetails(w, "Server error. Could not store updated appInfo.", http.StatusInternalServerError) + return } + // Respond with status 204 No Content to indicate successful update w.WriteHeader(http.StatusNoContent) } -- GitLab From fb58c301992796c00126892d56432775f9930604 Mon Sep 17 00:00:00 2001 From: Ikram Ul Haq Date: Wed, 6 Nov 2024 13:05:36 +0500 Subject: [PATCH 43/43] Fix implementation of query parameters for 'All Published Service APIs' resource --- .../server/capif-mgmt/service-mgmt.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go index afc2fd35a..11ce04b9c 100644 --- a/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go +++ b/go-apps/meep-app-enablement/server/capif-mgmt/service-mgmt.go @@ -909,16 +909,16 @@ func servicesGET(w http.ResponseWriter, r *http.Request) { // Validate query parameters u, _ := url.Parse(r.URL.String()) q := u.Query() - validParams := []string{"api-invoker-id"} - err := validateQueryParams(q, validParams) - if err != nil { - errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) - return - } // Extract and parse query parameters api_invoker_id := q.Get("api-invoker-id") if api_invoker_id != "" { + validParams := []string{"api-invoker-id"} + err := validateQueryParams(q, validParams) + if err != nil { + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } getServices(w, r, api_invoker_id) } else { getServices(w, r, "") -- GitLab