From 0c55d6bf44b7406ce558e6845ed35686f6822429 Mon Sep 17 00:00:00 2001 From: garciay Date: Fri, 11 Apr 2025 11:29:17 +0200 Subject: [PATCH 001/108] Partial validation of TTF T043 --- charts/meep-dai/templates/service.yaml | 2 +- docs/meep-sss/SensorDataSubscriptionApi.md | 2 +- docs/meep-sss/StatusDataSubscriptionIdBody.md | 2 +- go-apps/meep-iot/sbi/iot-sbi.go | 91 +++++ go-apps/meep-iot/server/meep-iot.go | 132 +++++- .../meep-sss/server/api_sensor_data_lookup.go | 3 +- go-apps/meep-sss/server/meep-sss.go | 104 ++++- .../model_status_data_subscription_id_body.go | 2 +- go-apps/meep-sss/server/routers.go | 8 +- go-packages/meep-iot-mgr/go.mod | 2 + go-packages/meep-iot-mgr/iot-mgr.go | 63 ++- go-packages/meep-iot-mgr/iot-mgr_test.go | 14 +- go-packages/meep-sss-client/README.md | 2 +- .../api_sensor_data_subscription.go | 2 +- .../model_status_data_subscription_id_body.go | 2 +- go-packages/meep-sss-mgr/mqtt.go | 89 ++-- go-packages/meep-sss-mgr/onem2m-mgr.go | 144 +++++-- go-packages/meep-sss-mgr/onem2m-mgr_test.go | 380 ++++++++++++------ go-packages/meep-vis-traffic-mgr/mqtt.go | 2 +- 19 files changed, 806 insertions(+), 240 deletions(-) diff --git a/charts/meep-dai/templates/service.yaml b/charts/meep-dai/templates/service.yaml index d4a7e020e..6548b7d6b 100644 --- a/charts/meep-dai/templates/service.yaml +++ b/charts/meep-dai/templates/service.yaml @@ -24,7 +24,7 @@ spec: port: 31120 targetPort: 31120 - name: onboarded-demo1 - port: 31121 + port: 31122 targetPort: 31122 - name: onboarded-demo2 port: 31123 diff --git a/docs/meep-sss/SensorDataSubscriptionApi.md b/docs/meep-sss/SensorDataSubscriptionApi.md index 2f3fca78f..ce4d3bc14 100644 --- a/docs/meep-sss/SensorDataSubscriptionApi.md +++ b/docs/meep-sss/SensorDataSubscriptionApi.md @@ -133,7 +133,7 @@ This method shall support the URI query parameters, request and response data st Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. - **body** | [**StatusDataSubscriptionIdBody**](StatusDataSubscriptionIdBody.md)| New SensorDataSubscription is included as entity body of the request | + **body** | [**SensorDataSubscriptionIdBody**](SensorDataSubscriptionIdBody.md)| New SensorDataSubscription is included as entity body of the request | **subscriptionId** | **string**| Unique identifiers of a subscription | ### Return type diff --git a/docs/meep-sss/StatusDataSubscriptionIdBody.md b/docs/meep-sss/StatusDataSubscriptionIdBody.md index 70a2b2e72..ed1b52db2 100644 --- a/docs/meep-sss/StatusDataSubscriptionIdBody.md +++ b/docs/meep-sss/StatusDataSubscriptionIdBody.md @@ -1,4 +1,4 @@ -# StatusDataSubscriptionIdBody +# SensorDataSubscriptionIdBody ## Properties Name | Type | Description | Notes diff --git a/go-apps/meep-iot/sbi/iot-sbi.go b/go-apps/meep-iot/sbi/iot-sbi.go index 253f899a0..57ae4f924 100644 --- a/go-apps/meep-iot/sbi/iot-sbi.go +++ b/go-apps/meep-iot/sbi/iot-sbi.go @@ -154,6 +154,7 @@ type TrafficFilter struct { SrcTunnelPort []string DstTunnelPort []string QCI int32 + DSCP int32 TC int32 } @@ -545,7 +546,52 @@ func convertDeviceInfoFromIotMgr(dev tm.DeviceInfo) (device DeviceInfo) { device.DeviceMetadata[i] = KeyValuePair{Key: k.Key, Value: k.Value} } // End of 'for' statement } + if len(dev.RequestedMecTrafficRule) != 0 { + device.RequestedMecTrafficRule = make([]TrafficRuleDescriptor, len(dev.RequestedMecTrafficRule)) + for i, v := range dev.RequestedMecTrafficRule { + device.RequestedMecTrafficRule[i] = TrafficRuleDescriptor{ + TrafficRuleId: v.TrafficRuleId, + FilterType: v.FilterType, + Priority: v.Priority, + Action: v.Action, + } + if len(dev.RequestedMecTrafficRule[i].TrafficFilter) != 0 { + device.RequestedMecTrafficRule[i].TrafficFilter = make([]TrafficFilter, len(dev.RequestedMecTrafficRule[i].TrafficFilter)) + for j, u := range dev.RequestedMecTrafficRule[i].TrafficFilter { + device.RequestedMecTrafficRule[i].TrafficFilter[j] = TrafficFilter{ + SrcAddress: u.SrcAddress, + DstAddress: u.DstAddress, + SrcPort: u.SrcPort, + DstPort: u.DstPort, + Protocol: u.Protocol, + Tag: u.Tag, + Uri: u.Uri, + PacketLabel: u.PacketLabel, + SrcTunnelAddress: u.SrcTunnelAddress, + TgtTunnelAddress: u.TgtTunnelAddress, + SrcTunnelPort: u.SrcTunnelPort, + DstTunnelPort: u.DstTunnelPort, + QCI: u.QCI, + DSCP: u.DSCP, + TC: u.TC, + } + } // End of 'for' statement + } + if v.DstInterface != nil { + device.RequestedMecTrafficRule[i].DstInterface = &InterfaceDescriptor{ + InterfaceType: device.RequestedMecTrafficRule[i].DstInterface.InterfaceType, + // FIXME FSCOM To be filled: TunnelInfo: nil, + SrcMACAddress: device.RequestedMecTrafficRule[i].DstInterface.SrcMACAddress, + DstMACAddress: device.RequestedMecTrafficRule[i].DstInterface.DstMACAddress, + DstIPAddress: device.RequestedMecTrafficRule[i].DstInterface.DstIPAddress, + } + } + } // End of 'for' statement + } // FIXME FSCOM Add missing fileds (pointers & arrays) + //DeviceSpecificMessageFormats *DeviceSpecificMessageFormats `json:"deviceSpecificMessageFormats,omitempty"` + //DownlinkInfo *DownlinkInfo `json:"downlinkInfo,omitempty"` + //log.Debug("convertDeviceInfoFromIotMgr: device: ", device) return device @@ -587,7 +633,52 @@ func convertDeviceInfoToIotMgr(dev DeviceInfo) (device tm.DeviceInfo) { device.DeviceMetadata[i] = tm.KeyValuePair{Key: k.Key, Value: k.Value} } // End of 'for' statement } + if len(dev.RequestedMecTrafficRule) != 0 { + device.RequestedMecTrafficRule = make([]tm.TrafficRuleDescriptor, len(dev.RequestedMecTrafficRule)) + for i, v := range dev.RequestedMecTrafficRule { + device.RequestedMecTrafficRule[i] = tm.TrafficRuleDescriptor{ + TrafficRuleId: v.TrafficRuleId, + FilterType: v.FilterType, + Priority: v.Priority, + Action: v.Action, + } + if len(dev.RequestedMecTrafficRule[i].TrafficFilter) != 0 { + device.RequestedMecTrafficRule[i].TrafficFilter = make([]tm.TrafficFilter, len(dev.RequestedMecTrafficRule[i].TrafficFilter)) + for j, u := range dev.RequestedMecTrafficRule[i].TrafficFilter { + device.RequestedMecTrafficRule[i].TrafficFilter[j] = tm.TrafficFilter{ + SrcAddress: u.SrcAddress, + DstAddress: u.DstAddress, + SrcPort: u.SrcPort, + DstPort: u.DstPort, + Protocol: u.Protocol, + Tag: u.Tag, + Uri: u.Uri, + PacketLabel: u.PacketLabel, + SrcTunnelAddress: u.SrcTunnelAddress, + TgtTunnelAddress: u.TgtTunnelAddress, + SrcTunnelPort: u.SrcTunnelPort, + DstTunnelPort: u.DstTunnelPort, + QCI: u.QCI, + DSCP: u.DSCP, + TC: u.TC, + } + } // End of 'for' statement + } + if v.DstInterface != nil { + device.RequestedMecTrafficRule[i].DstInterface = &tm.InterfaceDescriptor{ + InterfaceType: device.RequestedMecTrafficRule[i].DstInterface.InterfaceType, + // FIXME FSCOM To be filled: TunnelInfo: nil, + SrcMACAddress: device.RequestedMecTrafficRule[i].DstInterface.SrcMACAddress, + DstMACAddress: device.RequestedMecTrafficRule[i].DstInterface.DstMACAddress, + DstIPAddress: device.RequestedMecTrafficRule[i].DstInterface.DstIPAddress, + } + } + } // End of 'for' statement + } // FIXME FSCOM Add missing fileds (pointers & arrays) + //DeviceSpecificMessageFormats *DeviceSpecificMessageFormats `json:"deviceSpecificMessageFormats,omitempty"` + //DownlinkInfo *DownlinkInfo `json:"downlinkInfo,omitempty"` + //log.Debug("convertDeviceInfoToIotMgr: device: ", device) return device diff --git a/go-apps/meep-iot/server/meep-iot.go b/go-apps/meep-iot/server/meep-iot.go index aee94cfe5..ee77a0d3d 100644 --- a/go-apps/meep-iot/server/meep-iot.go +++ b/go-apps/meep-iot/server/meep-iot.go @@ -711,6 +711,7 @@ func registerediotplatformsPOST(w http.ResponseWriter, r *http.Request) { log.Debug(">>> registerediotplatformsPOST: ", r) w.Header().Set("Content-Type", "application/json; charset=UTF-8") + var requestData IotPlatformInfo decoder := json.NewDecoder(r.Body) err := decoder.Decode(&requestData) @@ -744,7 +745,12 @@ func registerediotplatformsPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, "Mandatory attribute Name shall be absent in the request body.", http.StatusBadRequest) return } - if v.Type_ == nil || *v.Type_ != "MB_TOPIC_BASED" { + if v.Type_ == nil { + log.Error("Mandatory Type_ parameter shall be present") + errHandlerProblemDetails(w, "Mandatory attribute Type_ shall be present.", http.StatusBadRequest) + return + } + if *v.Type_ != "MB_TOPIC_BASED" { log.Error("Mandatory Type_ parameter shall be set to MB_TOPIC_BASED") errHandlerProblemDetails(w, "Mandatory attribute Type_ shall be set to MB_TOPIC_BASED in the request body.", http.StatusBadRequest) return @@ -777,14 +783,8 @@ func registerediotplatformsPOST(w http.ResponseWriter, r *http.Request) { } } - if requestData.CustomServicesTransportInfo == nil || len(requestData.CustomServicesTransportInfo) == 0 { - log.Error("No information to register IoT platform") - errHandlerProblemDetails(w, "No information to register IoT platform.", http.StatusInternalServerError) - return - } - - _, ok := registeredIotPlatformsMap[requestData.IotPlatformId] - if ok { + log.Debug("registerediotplatformsPOST: registeredIotPlatformsMap (before): ", registeredIotPlatformsMap) + if _, ok := registeredIotPlatformsMap[requestData.IotPlatformId]; ok { log.Error("IoT platform already created") errHandlerProblemDetails(w, "IoT platform already created.", http.StatusBadRequest) return @@ -799,9 +799,10 @@ func registerediotplatformsPOST(w http.ResponseWriter, r *http.Request) { return } registeredIotPlatformsMap[responseData.IotPlatformId] = responseData - log.Debug("registerediotplatformsPOST: new registeredIotPlatformsMap: ", registeredIotPlatformsMap) + log.Debug("registerediotplatformsPOST: registeredIotPlatformsMap (after): ", registeredIotPlatformsMap) // Prepare & send response + w.Header().Set("Location", hostUrl.String()+basePath+"registered_iot_platforms/"+responseData.IotPlatformId) c := convertIotPlatformInfoFromSbi(responseData) jsonResponse := convertIoTPlatformInfotoJson(&c) w.WriteHeader(http.StatusCreated) @@ -861,6 +862,8 @@ func registereddevicesByIdGET(w http.ResponseWriter, r *http.Request) { func registereddevicesByIdPUT(w http.ResponseWriter, r *http.Request) { log.Debug(">>> registereddevicesByIdPUT: ", r) + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + errHandlerProblemDetails(w, "Not implemented yet", http.StatusBadRequest) } @@ -921,6 +924,7 @@ func registereddevicesGET(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, string(jsonResponse)) w.WriteHeader(http.StatusOK) } + func applyFiltering(devicesList []sbi.DeviceInfo, filter []string) (devices []DeviceInfo, err error) { log.Debug(">>> applyFiltering") devices, err = convertDeviceInfosFromSbi_with_filter(devicesList, filter) @@ -931,6 +935,8 @@ func applyFiltering(devicesList []sbi.DeviceInfo, filter []string) (devices []De func registereddevicesPOST(w http.ResponseWriter, r *http.Request) { log.Debug(">>> registereddevicesPOST: ", r) + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + // Read JSON input stream provided in the Request, and stores it in the bodyBytes as bytes var deviceInfo DeviceInfo bodyBytes, _ := ioutil.ReadAll(r.Body) @@ -966,16 +972,18 @@ func registereddevicesPOST(w http.ResponseWriter, r *http.Request) { errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) return } - log.Info("registereddevicesPOST: deviceInfoResp: ", deviceInfoResp) + devInfoResp := convertDeviceInfoFromSbi(deviceInfoResp) + log.Info("registereddevicesPOST: devInfoResp: ", devInfoResp) - jsonResponse, err := json.Marshal(deviceInfoResp) + // Prepare & send the reponse + w.Header().Set("Location", hostUrl.String()+basePath+"registered_devices/"+devInfoResp.DeviceId) + jsonResponse, err := json.Marshal(devInfoResp) if err != nil { log.Error(err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) return } log.Info("registereddevicesPOST: jsonResponse: ", string(jsonResponse)) - w.WriteHeader(http.StatusCreated) fmt.Fprint(w, string(jsonResponse)) } @@ -1057,6 +1065,7 @@ func convertIotPlatformInfoFromSbi(val sbi.IotPlatformInfo) (item IotPlatformInf } } e.Extensions = userTransportInfo.Security.Extensions + v.Security = &e } if userTransportInfo.ImplSpecificInfo != nil { v.ImplSpecificInfo = &ImplSpecificInfo{ @@ -1138,6 +1147,7 @@ func convertIotPlatformInfoToSbi(val IotPlatformInfo) (item sbi.IotPlatformInfo) } } e.Extensions = userTransportInfo.Security.Extensions + v.Security = &e } if userTransportInfo.ImplSpecificInfo != nil { v.ImplSpecificInfo = &sbi.ImplSpecificInfo{ @@ -1147,7 +1157,7 @@ func convertIotPlatformInfoToSbi(val IotPlatformInfo) (item sbi.IotPlatformInfo) } } item.UserTransportInfo = append(item.UserTransportInfo, v) - } + } // End of 'for' statement if val.CustomServicesTransportInfo != nil && len(val.CustomServicesTransportInfo) != 0 { item.CustomServicesTransportInfo = make([]sbi.TransportInfo, 0) for _, customServicesTransportInfo := range val.CustomServicesTransportInfo { @@ -1176,7 +1186,7 @@ func convertIotPlatformInfoToSbi(val IotPlatformInfo) (item sbi.IotPlatformInfo) v.Endpoint = &e } item.CustomServicesTransportInfo = append(item.CustomServicesTransportInfo, v) - } + } // End of 'for' statement } return item @@ -1204,9 +1214,53 @@ func convertDeviceInfoFromSbi(dev sbi.DeviceInfo) (device DeviceInfo) { device.DeviceMetadata[i] = KeyValuePair{Key: k.Key, Value: k.Value} } // End of 'for' statement } + if len(dev.RequestedMecTrafficRule) != 0 { + device.RequestedMecTrafficRule = make([]TrafficRuleDescriptor, len(dev.RequestedMecTrafficRule)) + for i, v := range dev.RequestedMecTrafficRule { + device.RequestedMecTrafficRule[i] = TrafficRuleDescriptor{ + TrafficRuleId: v.TrafficRuleId, + FilterType: v.FilterType, + Priority: v.Priority, + Action: v.Action, + } + if len(dev.RequestedMecTrafficRule[i].TrafficFilter) != 0 { + device.RequestedMecTrafficRule[i].TrafficFilter = make([]TrafficFilter, len(dev.RequestedMecTrafficRule[i].TrafficFilter)) + for j, u := range dev.RequestedMecTrafficRule[i].TrafficFilter { + device.RequestedMecTrafficRule[i].TrafficFilter[j] = TrafficFilter{ + SrcAddress: u.SrcAddress, + DstAddress: u.DstAddress, + SrcPort: u.SrcPort, + DstPort: u.DstPort, + Protocol: u.Protocol, + Tag: u.Tag, + Uri: u.Uri, + PacketLabel: u.PacketLabel, + SrcTunnelAddress: u.SrcTunnelAddress, + TgtTunnelAddress: u.TgtTunnelAddress, + SrcTunnelPort: u.SrcTunnelPort, + DstTunnelPort: u.DstTunnelPort, + QCI: u.QCI, + DSCP: u.DSCP, + TC: u.TC, + } + } // End of 'for' statement + } + if v.DstInterface != nil { + device.RequestedMecTrafficRule[i].DstInterface = &InterfaceDescriptor{ + InterfaceType: device.RequestedMecTrafficRule[i].DstInterface.InterfaceType, + TunnelInfo: nil, // FIXME FSCOM To be filled + SrcMACAddress: device.RequestedMecTrafficRule[i].DstInterface.SrcMACAddress, + DstMACAddress: device.RequestedMecTrafficRule[i].DstInterface.DstMACAddress, + DstIPAddress: device.RequestedMecTrafficRule[i].DstInterface.DstIPAddress, + } + } + } // End of 'for' statement + } // FIXME FSCOM Add missing fileds (pointers & arrays) - //log.Debug("convertDeviceInfosFromSbi: devices: ", devices) + //DeviceSpecificMessageFormats *DeviceSpecificMessageFormats `json:"deviceSpecificMessageFormats,omitempty"` + //DownlinkInfo *DownlinkInfo `json:"downlinkInfo,omitempty"` + //log.Debug("convertDeviceInfosFromSbi: devices: ", devices) return device } @@ -1284,8 +1338,52 @@ func convertDeviceInfoToSbi(dev DeviceInfo) (device sbi.DeviceInfo) { device.DeviceMetadata[i] = sbi.KeyValuePair{Key: k.Key, Value: k.Value} } // End of 'for' statement } + if len(dev.RequestedMecTrafficRule) != 0 { + device.RequestedMecTrafficRule = make([]sbi.TrafficRuleDescriptor, len(dev.RequestedMecTrafficRule)) + for i, v := range dev.RequestedMecTrafficRule { + device.RequestedMecTrafficRule[i] = sbi.TrafficRuleDescriptor{ + TrafficRuleId: v.TrafficRuleId, + FilterType: v.FilterType, + Priority: v.Priority, + Action: v.Action, + } + if len(dev.RequestedMecTrafficRule[i].TrafficFilter) != 0 { + device.RequestedMecTrafficRule[i].TrafficFilter = make([]sbi.TrafficFilter, len(dev.RequestedMecTrafficRule[i].TrafficFilter)) + for j, u := range dev.RequestedMecTrafficRule[i].TrafficFilter { + device.RequestedMecTrafficRule[i].TrafficFilter[j] = sbi.TrafficFilter{ + SrcAddress: u.SrcAddress, + DstAddress: u.DstAddress, + SrcPort: u.SrcPort, + DstPort: u.DstPort, + Protocol: u.Protocol, + Tag: u.Tag, + Uri: u.Uri, + PacketLabel: u.PacketLabel, + SrcTunnelAddress: u.SrcTunnelAddress, + TgtTunnelAddress: u.TgtTunnelAddress, + SrcTunnelPort: u.SrcTunnelPort, + DstTunnelPort: u.DstTunnelPort, + QCI: u.QCI, + DSCP: u.DSCP, + TC: u.TC, + } + } // End of 'for' statement + } + if v.DstInterface != nil { + device.RequestedMecTrafficRule[i].DstInterface = &sbi.InterfaceDescriptor{ + InterfaceType: device.RequestedMecTrafficRule[i].DstInterface.InterfaceType, + // FIXME FSCOM To be filled: TunnelInfo: nil, + SrcMACAddress: device.RequestedMecTrafficRule[i].DstInterface.SrcMACAddress, + DstMACAddress: device.RequestedMecTrafficRule[i].DstInterface.DstMACAddress, + DstIPAddress: device.RequestedMecTrafficRule[i].DstInterface.DstIPAddress, + } + } + } // End of 'for' statement + } // FIXME FSCOM Add missing fileds (pointers & arrays) - //log.Debug("convertDeviceInfoToSbi: devices: ", devices) + //DeviceSpecificMessageFormats *DeviceSpecificMessageFormats `json:"deviceSpecificMessageFormats,omitempty"` + //DownlinkInfo *DownlinkInfo `json:"downlinkInfo,omitempty"` + //log.Debug("convertDeviceInfoToSbi: devices: ", devices) return device } diff --git a/go-apps/meep-sss/server/api_sensor_data_lookup.go b/go-apps/meep-sss/server/api_sensor_data_lookup.go index 191b7a8a6..194094776 100644 --- a/go-apps/meep-sss/server/api_sensor_data_lookup.go +++ b/go-apps/meep-sss/server/api_sensor_data_lookup.go @@ -14,6 +14,5 @@ import ( ) func SensorDataLookupGET(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) + sensorDataLookupGET(w, r) } diff --git a/go-apps/meep-sss/server/meep-sss.go b/go-apps/meep-sss/server/meep-sss.go index d07e22f94..db7e595d8 100644 --- a/go-apps/meep-sss/server/meep-sss.go +++ b/go-apps/meep-sss/server/meep-sss.go @@ -606,10 +606,20 @@ func sensorDiscoveryLookupGET(w http.ResponseWriter, r *http.Request) { log.Debug("sensorDiscoveryLookupGET: q: ", q) if len(q) == 0 { err := errors.New("Invalid query parameters") + log.Error("sensorDiscoveryLookupGET: ", err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } else if _, ok := q["type"]; !ok { + err := errors.New("Invalid query parameters: type parameter is mandatory") + log.Error("sensorDiscoveryLookupGET: ", err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } else if len(q["type"][0]) == 0 { + err := errors.New("Invalid query parameters: Wrong type parameter value") + log.Error("sensorDiscoveryLookupGET: ", err.Error()) errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) return } - log.Debug("sensorDiscoveryLookupGET: q[type][0]: ", q["type"][0]) //log.Debug("sensorDiscoveryLookupGET: q[sensorCharacteristicList][0]: ", q["sensorCharacteristicList"][0]) //log.Debug("sensorDiscoveryLookupGET: type(q[sensorCharacteristicList][0]): ", reflect.TypeOf(q["sensorCharacteristicList"][0])) //q: map[geographicalArea:[[object Object]] sensorCharacteristicList:[[object Object]] sensorPropertyList:[string1,string2] type:[string]]","time":"2025-02-04T08:35:35Z"} @@ -634,7 +644,7 @@ func sensorDiscoveryLookupGET(w http.ResponseWriter, r *http.Request) { // Prepare response and send jsonResponse := convertSensorDiscoveryInfoListToJson(sensors) if jsonResponse == "" { - log.Error("Marshalling failure") + log.Error("sensorDiscoveryLookupGET: Marshalling failure") errHandlerProblemDetails(w, "Marshalling failure", http.StatusInternalServerError) return } @@ -656,6 +666,10 @@ func sensorStatusLookupGET(w http.ResponseWriter, r *http.Request) { err := errors.New("Invalid query parameters") errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) return + } else if len(q["sensorIdentifier"][0]) == 0 { + err := errors.New("Invalid query parameters") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return } log.Debug("sensorStatusLookupGET: q[sensorIdentifier][0]: ", q["sensorIdentifier"][0]) @@ -669,7 +683,7 @@ func sensorStatusLookupGET(w http.ResponseWriter, r *http.Request) { // Prepare response and send jsonResponse := convertSensorStatusToJson(convertSensorStatusInfoFromSbi(s)) if jsonResponse == "" { - log.Error("Marshalling failure") + log.Error("sensorDiscoveryLookupGET: Marshalling failure") errHandlerProblemDetails(w, "Marshalling failure", http.StatusInternalServerError) return } @@ -678,6 +692,45 @@ func sensorStatusLookupGET(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } +func sensorDataLookupGET(w http.ResponseWriter, r *http.Request) { + log.Debug(">>> sensorDataLookupGET: ", r) + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + + // Validate query parameters + u, _ := url.Parse(r.URL.String()) + q := u.Query() + log.Debug("sensorDataLookupGET: q: ", q) + if _, ok := q["sensorIdentifier"]; !ok { + err := errors.New("Invalid query parameters") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } else if len(q["sensorIdentifier"][0]) == 0 { + err := errors.New("Invalid query parameters") + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + log.Debug("sensorDataLookupGET: q[sensorIdentifier][0]: ", q["sensorIdentifier"][0]) + + s, err := sbi.GetSensorStatus(q["sensorIdentifier"][0]) + if err != nil { + errHandlerProblemDetails(w, err.Error(), http.StatusInternalServerError) + return + } + log.Debug("sensorDataLookupGET: s: ", s) + + // Prepare response and send + jsonResponse := convertSensorStatusToJson(convertSensorStatusInfoFromSbi(s)) + if jsonResponse == "" { + log.Error("sensorDataLookupGET: Marshalling failure") + errHandlerProblemDetails(w, "Marshalling failure", http.StatusInternalServerError) + return + } + log.Info("sensorDataLookupGET: jsonResponse: ", jsonResponse) + fmt.Fprint(w, jsonResponse) + w.WriteHeader(http.StatusOK) +} + func sensorDiscoverySubscriptionGET(w http.ResponseWriter, r *http.Request) { log.Debug(">>> sensorDiscoverySubscriptionGET: ", r) @@ -695,6 +748,7 @@ func sensorDataSubscriptionGET(w http.ResponseWriter, r *http.Request) { subscriptionsGET(SENS_DATA, w, r) } + func sensorDiscoverySubscriptionPOST(w http.ResponseWriter, r *http.Request) { log.Debug(">>> sensorDiscoverySubscriptionPOST: ", r) @@ -785,13 +839,13 @@ func subscriptionsPOST(subType string, w http.ResponseWriter, r *http.Request) { // create a unique link for every subscription and concatenate subscription to it link := new(SubscriptionLinks) self := new(LinkType) - self.Href = hostUrl.String() + basePath + "subscriptions/" + subsIdStr - link.Self = self // switch statement is based on provided subscriptionType in the request body var jsonResponse string switch subscriptionType { case SENS_DISCOVERY: + self.Href = hostUrl.String() + basePath + "subscriptions/sensor_discovery/" + subsIdStr + link.Self = self var sensorDiscoveryEventSubscription SensorDiscoveryEventSubscription jsonResponse, err = processSensorDiscoveryEventSubscription(bodyBytes, link, subsIdStr, &sensorDiscoveryEventSubscription) if err != nil { @@ -802,6 +856,8 @@ func subscriptionsPOST(subType string, w http.ResponseWriter, r *http.Request) { w.Header().Set("Location", sensorDiscoveryEventSubscription.Links.Self.Href) case SENS_STATUS: + self.Href = hostUrl.String() + basePath + "subscriptions/sensor_status/" + subsIdStr + link.Self = self var sensorStatusSubscription SensorStatusSubscription jsonResponse, err = processSensorStatusSubscription(bodyBytes, link, subsIdStr, &sensorStatusSubscription) if err != nil { @@ -812,6 +868,8 @@ func subscriptionsPOST(subType string, w http.ResponseWriter, r *http.Request) { w.Header().Set("Location", sensorStatusSubscription.Links.Self.Href) case SENS_DATA: + self.Href = hostUrl.String() + basePath + "subscriptions/sensor_data/" + subsIdStr + link.Self = self var sensorDataSubscription SensorDataSubscription jsonResponse, err = processSensorDataSubscription(bodyBytes, link, subsIdStr, &sensorDataSubscription) if err != nil { @@ -858,13 +916,27 @@ func subscriptionsGET(subType string, w http.ResponseWriter, r *http.Request) { u, _ := url.Parse(r.URL.String()) log.Info("url: ", u.RequestURI()) q := u.Query() - sensorIdentifier := q.Get("sensorIdentifier") - log.Debug("subscriptionsGET: sensorIdentifier: ", sensorIdentifier) - sensorIdentifiers := strings.Split(sensorIdentifier, ",") + sensorIdentifiers := []string{} + if len(q) != 0 { + sensorIdentifier := q.Get("sensorIdentifier") + if len(sensorIdentifier) == 0 { + err := errors.New("Wrong query parameters") + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } + log.Debug("subscriptionsGET: sensorIdentifier: ", sensorIdentifier) + sensorIdentifiers = strings.Split(sensorIdentifier, ",") + } log.Debug("subscriptionsGET: sensorIdentifiers: ", sensorIdentifiers) // get the response against particular subscription type - response := createSubscriptionLinkList(subType, sensorIdentifiers) + response, err := createSubscriptionLinkList(subType, sensorIdentifiers) + if err != nil { + log.Error(err.Error()) + errHandlerProblemDetails(w, err.Error(), http.StatusBadRequest) + return + } // prepare & send response jsonResponse, err := json.Marshal(response) @@ -1476,7 +1548,7 @@ func isSubscriptionIdRegisteredSensorData(subsIdStr string) bool { return returnVal } -func createSubscriptionLinkList(subType string, sensorIdentifiers []string) *SubscriptionLinkList { +func createSubscriptionLinkList(subType string, sensorIdentifiers []string) (*SubscriptionLinkList, error) { log.Debug(">>> createSubscriptionLinkList: subType: ", subType) log.Debug(">>> createSubscriptionLinkList: sensorIdentifiers: ", sensorIdentifiers) @@ -1553,7 +1625,7 @@ func createSubscriptionLinkList(subType string, sensorIdentifiers []string) *Sub subscriptionLinkList.Links = links - return subscriptionLinkList + return subscriptionLinkList, nil } /* @@ -1845,8 +1917,9 @@ func convertSensorDiscoveryInfoListFromSbi_with_filter(s []sbi.SensorDiscoveryIn func convertSensorDiscoveryInfoFromSbi(s sbi.SensorDiscoveryInfo) (sensor SensorDiscoveryInfo) { sensor = SensorDiscoveryInfo{ - SensorIdentifier: s.SensorIdentifier, - SensorType: s.SensorType, + SensorIdentifier: s.SensorIdentifier, + SensorType: s.SensorType, + SensorPropertyList: []string{"SAREF"}, } if len(s.SensorPropertyList) != 0 { copy(sensor.SensorPropertyList, s.SensorPropertyList) @@ -1866,6 +1939,11 @@ func convertSensorDiscoveryInfoFromSbi(s sbi.SensorDiscoveryInfo) (sensor Sensor Latitude: s.SensorPosition.Latitude, Longitude: s.SensorPosition.Longitude, } + } else { // SensorPosition is mandatory + sensor.SensorPosition = &Point{ + Latitude: 0, + Longitude: 0, + } } return sensor diff --git a/go-apps/meep-sss/server/model_status_data_subscription_id_body.go b/go-apps/meep-sss/server/model_status_data_subscription_id_body.go index f6b6594b6..c6fa315bc 100644 --- a/go-apps/meep-sss/server/model_status_data_subscription_id_body.go +++ b/go-apps/meep-sss/server/model_status_data_subscription_id_body.go @@ -9,6 +9,6 @@ */ package server -type StatusDataSubscriptionIdBody struct { +type SensorDataSubscriptionIdBody struct { SensorStatusSubscription *SensorDataSubscription `json:"SensorStatusSubscription,omitempty"` } diff --git a/go-apps/meep-sss/server/routers.go b/go-apps/meep-sss/server/routers.go index 35b06a0db..a8d164cf5 100644 --- a/go-apps/meep-sss/server/routers.go +++ b/go-apps/meep-sss/server/routers.go @@ -83,21 +83,21 @@ var routes = Routes{ Route{ "SensorDataLookupGET", strings.ToUpper("Get"), - "/sens/v1/queries/status_data", + "/sens/v1/queries/sensor_data", SensorDataLookupGET, }, Route{ "SensorDataIndividualSubscriptionGET", strings.ToUpper("Get"), - "/sens/v1/queries/status_data/{subscriptionId}", + "/sens/v1/queries/sensor_data/{subscriptionId}", SensorDataIndividualSubscriptionGET, }, Route{ "SensorDataSubscriptionDELETE", strings.ToUpper("Delete"), - "/sens/v1/queries/status_data/{subscriptionId}", + "/sens/v1/queries/sensor_data/{subscriptionId}", SensorDataSubscriptionDELETE, }, @@ -118,7 +118,7 @@ var routes = Routes{ Route{ "SensorDataSubscriptionPUT", strings.ToUpper("Put"), - "/sens/v1/queries/status_data/{subscriptionId}", + "/sens/v1/queries/sensor_data/{subscriptionId}", SensorDataSubscriptionPUT, }, diff --git a/go-packages/meep-iot-mgr/go.mod b/go-packages/meep-iot-mgr/go.mod index d9b09212a..c082d159a 100644 --- a/go-packages/meep-iot-mgr/go.mod +++ b/go-packages/meep-iot-mgr/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/BurntSushi/toml v1.2.0 // indirect + github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sss-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger v0.0.0 github.com/eclipse/paho.mqtt.golang v1.4.2 github.com/google/uuid v1.6.0 @@ -16,4 +17,5 @@ require ( replace ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger => ../../go-packages/meep-logger + github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sss-mgr => ../../go-packages/meep-sss-mgr ) diff --git a/go-packages/meep-iot-mgr/iot-mgr.go b/go-packages/meep-iot-mgr/iot-mgr.go index a517df845..f4b7d34f6 100644 --- a/go-packages/meep-iot-mgr/iot-mgr.go +++ b/go-packages/meep-iot-mgr/iot-mgr.go @@ -125,6 +125,7 @@ type TrafficFilter struct { SrcTunnelPort []string DstTunnelPort []string QCI int32 + DSCP int32 TC int32 } @@ -153,10 +154,11 @@ type DeviceInfo struct { Enabled bool } -var registeredIotPlatformsMap = map[string]IotPlatformInfo{} // List of discovered IOT Plateform -var devicesMap = map[string]DeviceInfo{} // Map device by deviceId -var devicesPerPlatformMap = map[string][]string{} // Map deviceIds per platform -var platformPerUserTransportIdMap = map[string][]string{} // Map userTransportId per platform +var registeredIotPlatformsMap = map[string]IotPlatformInfo{} // List of discovered IOT Plateform +var devicesMap = map[string]DeviceInfo{} // Map device by deviceId +var devicesPerPlatformMap = map[string][]string{} // Map deviceIds per platform +var platformPerUserTransportIdMap = map[string][]string{} // Map userTransportId per platform +var registeredIotPlatformsAEMap = map[string]sssmgr.SensorDiscoveryInfo{} // Map AE created per IOT Plateform // Timer to refresh devices list for all IoT platform const refreshTickerExpeary = 30 // In seconds @@ -202,11 +204,18 @@ func (tm *IotMgr) init() { devicesMap = make(map[string]DeviceInfo, 0) devicesPerPlatformMap = make(map[string][]string, 0) platformPerUserTransportIdMap = make(map[string][]string, 0) + registeredIotPlatformsAEMap = make(map[string]sssmgr.SensorDiscoveryInfo, 0) tm.refreshTicker = nil } // DeleteIotMgr - func (tm *IotMgr) DeleteIotMgr() (err error) { + registeredIotPlatformsMap = nil + devicesMap = nil + devicesPerPlatformMap = nil + platformPerUserTransportIdMap = nil + registeredIotPlatformsAEMap = nil + tm.refreshTicker = nil return nil } @@ -219,7 +228,7 @@ func (tm *IotMgr) startRefreshTicker() { for range tm.refreshTicker.C { // Refresh the list of devices tm.wg.Add(1) - log.Debug("startRefreshTicker: registeredIotPlatformsMap: ", registeredIotPlatformsMap) + log.Debug("iotmgr.startRefreshTicker: registeredIotPlatformsMap: ", registeredIotPlatformsMap) for _, v := range registeredIotPlatformsMap { if v.oneM2M != nil { err := tm.populateDevicesPerIotPlatforms(v) @@ -227,14 +236,14 @@ func (tm *IotMgr) startRefreshTicker() { log.Error(err) } } else { - log.Debug("startRefreshTicker: Nothing to do") + log.Debug("iotmgr.startRefreshTicker: Nothing to do") } } // End of 'for' statement - log.Debug("startRefreshTicker: Before Done()") + log.Debug("iotmgr.startRefreshTicker: Before Done()") tm.wg.Done() - log.Debug("startRefreshTicker: After Done()") + log.Debug("iotmgr.startRefreshTicker: After Done()") } // End of 'for' statement - log.Debug("startRefreshTicker: Leaving time loop") + log.Debug("iotmgr.startRefreshTicker: Leaving time loop") } }() } @@ -257,20 +266,33 @@ func (tm *IotMgr) RegisterIotPlatformInfo(iotPlatformInfo IotPlatformInfo) (err log.Info(">>> RegisterIotPlatformInfo: iotPlatformId: ", iotPlatformInfo) if iotPlatformInfo.Enabled { - //{{\"iotPlatformId\": \"1a584db5-6a3e-4f56-b126-29180069ecf1\", \"userTransportInfo\": [{\"id\": \"ca22ca5e-e0ce-4da8-a2ce-2966f4759032\", \"name\": \"MQTT\", \"description\": \"MQTT\", \"type\": \"MB_TOPIC_BASED\", \"protocol\": \"MQTT\", \"version\": \"2\", \"endpoint\": {\"addresses\": [{\"host\": \"172.29.10.56\", \"port\": 1883}]}, \"security\": {}, \"implSpecificInfo\": {}}], \"customServicesTransportInfo\": [{\"id\": \"85fe5e7f-c371-4f71-b7f6-61a1f808fbb3\", \"name\": \"/laboai-acme-ic-cse\", \"description\": \"ACME oneM2M CSE\", \"type\": \"REST_HTTP\", \"protocol\": \"REST_HTTP\", \"version\": \"4\", \"endpoint\": {\"addresses\": [{\"host\": \"172.29.10.20\", \"port\": 31110}]}, \"security\": {}}], \"enabled\": true}} iotPlatformInfo.oneM2M = nil - if len(iotPlatformInfo.CustomServicesTransportInfo) == 0 || iotPlatformInfo.CustomServicesTransportInfo[0].Endpoint == nil || len(iotPlatformInfo.CustomServicesTransportInfo[0].Endpoint.Addresses) == 0 { + if len(iotPlatformInfo.UserTransportInfo) == 0 || iotPlatformInfo.UserTransportInfo[0].Endpoint == nil || len(iotPlatformInfo.UserTransportInfo[0].Endpoint.Addresses) == 0 { log.Warn("RegisterIotPlatformInfo: Cannot use provided CustomServicesTransportInfo") } else { - // FIXME FSCOM How to get the CSE_ID + // FIXME FSCOM How to get the CSE_ID. For the time being, iotPlatformInfo.UserTransportInfo[0].Name is the CSE-resourceID // TODO FSCOM Add notification support? - pltf, err := sssmgr.NewSssMgr(tm.name, tm.namespace, iotPlatformInfo.CustomServicesTransportInfo[0].Protocol /*"MQTT"*/, iotPlatformInfo.CustomServicesTransportInfo[0].Endpoint.Addresses[0].Host /*"172.29.10.56"*/, int(iotPlatformInfo.CustomServicesTransportInfo[0].Endpoint.Addresses[0].Port) /*1883*/, iotPlatformInfo.IotPlatformId /*"7feaadbb0400"*/, iotPlatformInfo.CustomServicesTransportInfo[0].Name /*"laboai-acme-ic-cse"*/, nil, nil, nil) + pltf, err := sssmgr.NewSssMgr(tm.name, tm.namespace, iotPlatformInfo.UserTransportInfo[0].Protocol, iotPlatformInfo.UserTransportInfo[0].Endpoint.Addresses[0].Host, int(iotPlatformInfo.UserTransportInfo[0].Endpoint.Addresses[0].Port), iotPlatformInfo.IotPlatformId, iotPlatformInfo.UserTransportInfo[0].Name, nil, nil, nil) if err != nil { log.Error("RegisterIotPlatformInfo: ", err) iotPlatformInfo.oneM2M = nil } else { log.Info("RegisterIotPlatformInfo: IoT pltf created") iotPlatformInfo.oneM2M = pltf + // Create the an AE for this ETSI MEC platform + var ae = sssmgr.SensorDiscoveryInfo{ + SensorIdentifier: iotPlatformInfo.IotPlatformId, + SensorType: "AE", + SensorPosition: nil, + IotPlatformId: iotPlatformInfo.IotPlatformId, + } + ae, err = pltf.OneM2M_create(ae, "") + if err != nil { + log.Warn("RegisterIotPlatformInfo: Failed to create new AE sensor") + } else { + registeredIotPlatformsAEMap[iotPlatformInfo.IotPlatformId] = ae + } + registeredIotPlatformsAEMap[iotPlatformInfo.IotPlatformId] = ae if tm.refreshTicker == nil { log.Info("RegisterIotPlatformInfo: Start RefreshTicker") tm.startRefreshTicker() @@ -278,6 +300,7 @@ func (tm *IotMgr) RegisterIotPlatformInfo(iotPlatformInfo IotPlatformInfo) (err } } registeredIotPlatformsMap[iotPlatformInfo.IotPlatformId] = iotPlatformInfo + log.Info("RegisterIotPlatformInfo: iotPlatformId: ", registeredIotPlatformsMap[iotPlatformInfo.IotPlatformId]) } // else, Skip disabled platform @@ -314,6 +337,10 @@ func (tm *IotMgr) DeregisterIotPlatformInfo(iotPlatformId string) (err error) { } if pltf, ok := registeredIotPlatformsMap[iotPlatformId]; ok { if pltf.oneM2M != nil { + if val, ok := registeredIotPlatformsAEMap[iotPlatformId]; ok { + _ = pltf.oneM2M.OneM2M_delete(val) + delete(registeredIotPlatformsAEMap, iotPlatformId) + } _ = pltf.oneM2M.DeleteSssMgr() pltf.oneM2M = nil log.Info("RegisterIotPlatformInfo: IoT pltf removed") @@ -395,7 +422,7 @@ func (tm *IotMgr) CreateDevice(device DeviceInfo) (deviceResp DeviceInfo, err er log.Info(">>> CreateDevice: ", device) tm.wg.Wait() - log.Info("GetDevices: After Wait()") + log.Info("CreateDevice: After Wait()") // RequestedMecTrafficRule is not supported yet if len(device.RequestedMecTrafficRule) != 0 { @@ -471,6 +498,10 @@ func (tm *IotMgr) createDeviceWithIotPlatformId(device DeviceInfo, requestedIotP err = errors.New("Device already exist") return deviceResp, err } + if _, ok := registeredIotPlatformsAEMap[requestedIotPlatformId]; !ok { + err = errors.New("Devaice cannot be created witout oneM2M AE parent") + return deviceResp, err + } if registeredIotPlatformsMap[requestedIotPlatformId].oneM2M != nil && device.Enabled == true { log.Info("createDeviceWithIotPlatformId: Create device on IoT platform", device) @@ -500,7 +531,7 @@ func (tm *IotMgr) createDeviceWithIotPlatformId(device DeviceInfo, requestedIotP // //DownlinkInfo *DownlinkInfo // ClientCertificate string // } - sensor, err := registeredIotPlatformsMap[requestedIotPlatformId].oneM2M.OneM2M_create(sensor, "") + sensor, err := registeredIotPlatformsMap[requestedIotPlatformId].oneM2M.OneM2M_create(sensor, registeredIotPlatformsAEMap[requestedIotPlatformId].SensorIdentifier) if err != nil { return deviceResp, err } @@ -522,7 +553,7 @@ func (tm *IotMgr) createDeviceWithRequestedUserTransportId(device DeviceInfo, re if val, ok := platformPerUserTransportIdMap[requestedUserTransportId]; ok { deviceResp, err = tm.createDeviceWithIotPlatformId(device, val[0]) } else { - err = errors.New("Invalid UserTransportId") + err = errors.New("Invalid requestedUserTransportId") } if err != nil { log.Error("createDeviceWithIotPlatformId: ", err.Error()) diff --git a/go-packages/meep-iot-mgr/iot-mgr_test.go b/go-packages/meep-iot-mgr/iot-mgr_test.go index 84ca215aa..b9be619ad 100644 --- a/go-packages/meep-iot-mgr/iot-mgr_test.go +++ b/go-packages/meep-iot-mgr/iot-mgr_test.go @@ -74,10 +74,10 @@ func TestRegisterIotPlatformInfo(t *testing.T) { var userTransportInfo = []MbTransportInfo{} userTransportInfo = append(userTransportInfo, MbTransportInfo{ Id: "d5673793-c55c-4969-b5bc-2121f84b9f8d", - Name: "MQTT", + Name: "laboai-acme-ic-cse", Description: "MQTT", Protocol: "MQTT", - Version: "2", + Version: "3", Endpoint: &endpoint, }) var adresses_1 = []Addresses{} @@ -91,7 +91,7 @@ func TestRegisterIotPlatformInfo(t *testing.T) { } customServicesTransportInfo = append(customServicesTransportInfo, TransportInfo{ Id: "2ddb713c-2b41-4ded-a7ad-a5a047c5df13", - Name: "/laboai-acme-ic-cse", + Name: "laboai-acme-ic-cse", Description: "ACME oneM2M CSE", Protocol: "REST_HTTP", Version: "4", @@ -430,7 +430,7 @@ func registerIotPltf(tm *IotMgr) (iotPlatformInfo IotPlatformInfo, err error) { var userTransportInfo = []MbTransportInfo{} userTransportInfo = append(userTransportInfo, MbTransportInfo{ Id: "d5673793-c55c-4969-b5bc-2121f84b9f8d", - Name: "MQTT", + Name: "laboai-acme-ic-cse", Description: "MQTT", Protocol: "MQTT", Version: "2", @@ -447,7 +447,7 @@ func registerIotPltf(tm *IotMgr) (iotPlatformInfo IotPlatformInfo, err error) { } customServicesTransportInfo = append(customServicesTransportInfo, TransportInfo{ Id: "2ddb713c-2b41-4ded-a7ad-a5a047c5df13", - Name: "/laboai-acme-ic-cse", + Name: "laboai-acme-ic-cse", Description: "ACME oneM2M CSE", Protocol: "REST_HTTP", Version: "4", @@ -481,7 +481,7 @@ func registerIotPltfAndCreateDevice(tm *IotMgr) (iotPlatformInfo IotPlatformInfo var userTransportInfo = []MbTransportInfo{} userTransportInfo = append(userTransportInfo, MbTransportInfo{ Id: "d5673793-c55c-4969-b5bc-2121f84b9f8d", - Name: "MQTT", + Name: "laboai-acme-ic-cse", Description: "MQTT", Protocol: "MQTT", Version: "2", @@ -498,7 +498,7 @@ func registerIotPltfAndCreateDevice(tm *IotMgr) (iotPlatformInfo IotPlatformInfo } customServicesTransportInfo = append(customServicesTransportInfo, TransportInfo{ Id: "2ddb713c-2b41-4ded-a7ad-a5a047c5df13", - Name: "/laboai-acme-ic-cse", + Name: "laboai-acme-ic-cse", Description: "ACME oneM2M CSE", Protocol: "REST_HTTP", Version: "4", diff --git a/go-packages/meep-sss-client/README.md b/go-packages/meep-sss-client/README.md index 6bfa0a4cc..6fe84ed60 100644 --- a/go-packages/meep-sss-client/README.md +++ b/go-packages/meep-sss-client/README.md @@ -60,7 +60,7 @@ Class | Method | HTTP request | Description - [SensorStatusSubscription](docs/SensorStatusSubscription.md) - [SensorStatusSubscriptionIdBody](docs/SensorStatusSubscriptionIdBody.md) - [ShapeType](docs/ShapeType.md) - - [StatusDataSubscriptionIdBody](docs/StatusDataSubscriptionIdBody.md) + - [SensorDataSubscriptionIdBody](docs/SensorDataSubscriptionIdBody.md) - [SubscriptionLinkList](docs/SubscriptionLinkList.md) - [SubscriptionLinkListLinks](docs/SubscriptionLinkListLinks.md) - [SubscriptionLinkListSubscription](docs/SubscriptionLinkListSubscription.md) diff --git a/go-packages/meep-sss-client/api_sensor_data_subscription.go b/go-packages/meep-sss-client/api_sensor_data_subscription.go index c541e06a7..f551617a6 100644 --- a/go-packages/meep-sss-client/api_sensor_data_subscription.go +++ b/go-packages/meep-sss-client/api_sensor_data_subscription.go @@ -498,7 +498,7 @@ This method shall support the URI query parameters, request and response data st * @param subscriptionId Unique identifiers of a subscription @return []SensorDataSubscription */ -func (a *SensorDataSubscriptionApiService) SensorDataSubscriptionPUT(ctx context.Context, body StatusDataSubscriptionIdBody, subscriptionId string) ([]SensorDataSubscription, *http.Response, error) { +func (a *SensorDataSubscriptionApiService) SensorDataSubscriptionPUT(ctx context.Context, body SensorDataSubscriptionIdBody, subscriptionId string) ([]SensorDataSubscription, *http.Response, error) { var ( localVarHttpMethod = strings.ToUpper("Put") localVarPostBody interface{} diff --git a/go-packages/meep-sss-client/model_status_data_subscription_id_body.go b/go-packages/meep-sss-client/model_status_data_subscription_id_body.go index 0b09d725c..02e2be891 100644 --- a/go-packages/meep-sss-client/model_status_data_subscription_id_body.go +++ b/go-packages/meep-sss-client/model_status_data_subscription_id_body.go @@ -9,6 +9,6 @@ */ package client -type StatusDataSubscriptionIdBody struct { +type SensorDataSubscriptionIdBody struct { SensorStatusSubscription *SensorDataSubscription `json:"SensorStatusSubscription,omitempty"` } diff --git a/go-packages/meep-sss-mgr/mqtt.go b/go-packages/meep-sss-mgr/mqtt.go index 9eec0dde7..38784d1de 100644 --- a/go-packages/meep-sss-mgr/mqtt.go +++ b/go-packages/meep-sss-mgr/mqtt.go @@ -6,6 +6,7 @@ import ( "fmt" "reflect" "strconv" + "strings" "sync" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" @@ -30,7 +31,7 @@ func onMessageReceived(client mqtt.Client, msg mqtt.Message) { // if _notify != nil { // ... // } else { - // log.Info("onMessageReceived: null pointer for the callbacl") + // log.Info("onMessageReceived: null pointer for the callback") // } }() } @@ -41,7 +42,7 @@ func onMessageReceivedReq(client mqtt.Client, msg mqtt.Message) { // if _notify != nil { // ... // } else { - // log.Info("onMessageReceivedReq: null pointer for the callbacl") + // log.Info("onMessageReceivedReq: null pointer for the callback") // } }() } @@ -54,12 +55,57 @@ func onMessageReceivedResp(client mqtt.Client, msg mqtt.Message) { }() } +func onMessageReceivedNot(client mqtt.Client, msg mqtt.Message) { + go func() { + log.Info("onMessageReceivedNot: Received message: ", string(msg.Payload()), " on topic ", msg.Topic()) + //{\"fr\": \"/laboai-acme-ic-cse\", \"to\": \"mqtt://172.29.10.56:1883\", \"ot\": \"20250327T134413,103223\", \"op\": 5, \"rqi\": \"6400213617020980613\", \"rvi\": \"4\", \"drt\": 1, \"pc\": {\"m2m:sgn\": {\"nev\": {\"net\": 3, \"rep\": {\"m2m:cin\": {\"cnf\": \"text/plain:0\", \"con\": \"toto\", \"rn\": \"1234\", \"ri\": \"cin3503344383965775257\", \"pi\": \"cnt1992620086833081496\", \"ct\": \"20250327T134413,093784\", \"lt\": \"20250327T134413,093784\", \"ty\": 4, \"cs\": 4, \"st\": 2, \"et\": \"20300326T134347,108295\"}}}, \"sur\": \"/laboai-acme-ic-cse/sub3169944238694067800\"}}} on topic /oneM2M/req/laboai-acme-ic-cse/mqtt:::172.29.10.56:1883/json" + // Prepare response + s := strings.Split(msg.Topic(), "/") // /oneM2M/req/laboai-acme-ic-cse/mqtt:::172.29.10.56:1883/json + resp_topic := "/oneM2M/resp/" + s[4] + "/" + s[3] + "/" + s[5] + log.Debug("onMessageReceivedNot: resp_topic: ", resp_topic) + if _notify != nil { + var d map[string]interface{} + err := json.Unmarshal(msg.Payload(), &d) + if err != nil { + log.Warn("onMessageReceivedNot: ", err.Error()) + return + } + if pc, ok := d["pc"]; ok { + log.Debug("onMessageReceivedNot: pc: ", pc) + log.Debug("onMessageReceivedNot: TypeOf(pc): ", reflect.TypeOf(pc)) + if _, ok := d["pc"].(map[string]interface{}); !ok { + log.Warn("onMessageReceivedNot: pc entry has an unexpected type") + return + } + body := d["pc"].(map[string]interface{}) + if _, ok := body["m2m:sgn"]; !ok { + log.Error("Only m2m:sgn is expected") + return + } + if _, ok := body["m2m:sgn"].(map[string]interface{}); !ok { + log.Warn("onMessageReceivedNot: m2m:sgn entry has an unexpected type") + return + } + m := body["m2m:sgn"].(map[string]interface{}) + log.Info("handleRoot: m: ", m) + _notify(m) + } else { + log.Warn("onMessageReceivedNot: pc entry not found") + return + } + } else { + log.Debug("onMessageReceivedNot: null pointer for the callback") + } + // FIXME FSCOM Send the response + }() +} + var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { - log.Info("mqtt.OnConnectHandler: Connected") + //log.Info("mqtt.OnConnectHandler: Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { - log.Info("Connect lost:", err) + //log.Info("Connect lost:", err) } func NewSssMgrMqtt() (broker_mqtt *SssMgrMqtt) { @@ -76,7 +122,7 @@ func (broker_mqtt *SssMgrMqtt) init(tm *SssMgr, notify func(map[string]interface broker_mqtt.opts = mqtt.NewClientOptions() broker_mqtt.opts.SetDefaultPublishHandler(onMessageReceived) - broker_mqtt.opts.SetClientID("AdvantEDGE.meep-vis-traffic-mgr") + broker_mqtt.opts.SetClientID("AdvantEDGE.meep-sss-mgr") broker_mqtt.opts.OnConnect = connectHandler broker_mqtt.opts.OnConnectionLost = connectLostHandler broker_mqtt.opts.CleanSession = true @@ -95,15 +141,25 @@ func (broker_mqtt *SssMgrMqtt) init(tm *SssMgr, notify func(map[string]interface token.Wait() // Subscribe - log.Info("init: Subscribe to: ", "oneM2M/req/+") - token = broker_mqtt.client.Subscribe("oneM2M/req/+", 0, onMessageReceivedReq) // qos:0 + // tp := "/oneM2M/req/+/" + tm.cse_name + "/#" + // log.Info("init: Subscribe to: ", tp) + // token = broker_mqtt.client.Subscribe(tp, 0, onMessageReceivedReq) // qos:0 + // if token.Error() != nil { + // log.Error(token.Error()) + // return token.Error() + // } + // token.Wait() + tp := "/oneM2M/resp/+/" + tm.cse_name + "/#" + log.Info("init: Subscribe to: ", tp) + token = broker_mqtt.client.Subscribe(tp, 0, onMessageReceivedResp) // qos:0 if token.Error() != nil { log.Error(token.Error()) return token.Error() } - // token.Wait() - log.Info("init: Subscribe to: ", "/oneM2M/resp/#") - token = broker_mqtt.client.Subscribe("/oneM2M/resp/#", 0, onMessageReceivedResp) // qos:0 + token.Wait() + tp = "/oneM2M/req/" + tm.cse_name + "/+/#" + log.Info("init: Subscribe to: ", tp) + token = broker_mqtt.client.Subscribe(tp, 1, onMessageReceivedNot) // qos:1 if token.Error() != nil { log.Error(token.Error()) return token.Error() @@ -222,19 +278,6 @@ func (broker_mqtt *SssMgrMqtt) send(p_ctx SssMgrBindingProtocolContext) (err err if r, ok := d["pc"]; ok { log.Debug("send: r: ", r) log.Debug("send: TypeOf(r): ", reflect.TypeOf(r)) - // var b []byte - // b, err = json.Marshal(r) - // if err != nil { - // log.Error("send: ", err.Error()) - // return err, nil - // } - // log.Info("send: b: ", b) - // log.Info("send: TypeOf(b): ", reflect.TypeOf(b)) - // err = json.Unmarshal(b, &resp) - // if err != nil { - // log.Error("send: ", err.Error()) - // return err, nil - // } return nil, r } return err, nil diff --git a/go-packages/meep-sss-mgr/onem2m-mgr.go b/go-packages/meep-sss-mgr/onem2m-mgr.go index ceebba77f..6b6d76b41 100644 --- a/go-packages/meep-sss-mgr/onem2m-mgr.go +++ b/go-packages/meep-sss-mgr/onem2m-mgr.go @@ -72,6 +72,7 @@ type SensorDiscoveryInfo struct { SensorCharacteristicList []SensorCharacteristic SensorPosition *Point IotPlatformId string + Flex map[string]interface{} } var registeredIotPlatformsMap = map[string]IotPlatformInfo{} // List of discovered IOT Plateform @@ -193,7 +194,7 @@ func (tm *SssMgr) DeleteSssMgr() (err error) { } func (tm *SssMgr) startRefreshTicker() { - log.Debug("Starting refresh loop") + log.Debug(">>> sssmgr.startRefreshTicker") tm.refreshTicker = time.NewTicker(refreshTickerExpeary * time.Second) go func() { if tm.refreshTicker != nil { @@ -204,8 +205,11 @@ func (tm *SssMgr) startRefreshTicker() { if err != nil { log.Error(err) } + log.Debug("sssmgr.startRefreshTicker: Before Done()") tm.wg.Done() - } + log.Debug("sssmgr.startRefreshTicker: Before Done()") + } // End of 'for' statement + log.Debug("sssmgr.startRefreshTicker: Leaving time loop") } }() } @@ -304,7 +308,12 @@ func (tm *SssMgr) populateDevicesPerIotPlatforms() error { // Refresh the list of devices for all registered Iot platform for _, iotPlatform := range registeredIotPlatformsMap { log.Debug("populateDevicesPerIotPlatforms: processing: ", iotPlatform.Address) - err := tm.populateSensors(iotPlatform) + err := tm.populateSensors(iotPlatform, "3") + if err != nil { + log.Error("populateDevicesPerIotPlatforms: ", err) + continue + } + err = tm.populateSensors(iotPlatform, "28") if err != nil { log.Error("populateDevicesPerIotPlatforms: ", err) continue @@ -324,7 +333,7 @@ func (tm *SssMgr) populateDevicesPerIotPlatforms() error { * @param {string} iotPlatformId contains the IoT platform identifier * @return {struct} nil on success, error otherwise */ -func (tm *SssMgr) populateSensors(iotPlatformInfo IotPlatformInfo) error { +func (tm *SssMgr) populateSensors(iotPlatformInfo IotPlatformInfo, type_ string) error { if profiling { profilingTimers["populateSensors"] = time.Now() } @@ -348,7 +357,7 @@ func (tm *SssMgr) populateSensors(iotPlatformInfo IotPlatformInfo) error { // Build the queries queries := map[string]string{} queries["fu"] = "1" // Filter usage - queries["ty"] = "3" // FIXME FSCOM Filter on oneM2M CNT for sensors or on AE because AE if the platform and CNT is a sensor and CIN the values + queries["ty"] = type_ ctx.queries = queries err, resp := protocol.send(ctx) @@ -375,12 +384,12 @@ func (tm *SssMgr) populateSensors(iotPlatformInfo IotPlatformInfo) error { ctx.queries["fu"] = "2" err, resp := protocol.send(ctx) if err != nil { - log.Error("OneM2M_create: ", err.Error()) + log.Error("populateSensors: ", err.Error()) continue } log.Debug("populateSensors: resp: ", resp) log.Debug("populateSensors: type(resp): ", reflect.TypeOf(resp)) - if resp.(map[string]interface{}) == nil || resp.(map[string]interface{})["m2m:cnt"] == nil { + if resp.(map[string]interface{}) == nil { continue } // oneM2M_cin := resp.(map[string]interface{})["m2m:cnt"].(map[string]interface{}) @@ -390,6 +399,11 @@ func (tm *SssMgr) populateSensors(iotPlatformInfo IotPlatformInfo) error { var sensor = SensorDiscoveryInfo{ IotPlatformId: iotPlatformInfo.IotPlatformId, } + if type_ == "28" { + sensor.SensorType = "FLX" + sensor.Flex = map[string]interface{}{} // FIXME FSCOM How to create flex container map from list of attributes recieved? Q&D: extract all attributes != attributes[AE/CNT/CNI]??? + // ==> Use cnd which contains the link to download the onthology or the reference to the oneM2M standard + } sensor, err = tm.oneM2M_deserialize(sensor, resp.(map[string]interface{})) if err != nil { log.Warn("populateSensors: ", err.Error()) @@ -468,6 +482,38 @@ func (tm *SssMgr) OneM2M_create(sensor SensorDiscoveryInfo, path string) (sensor bodyMap["m2m:cin"][val.CharacteristicName] = val.CharacteristicValue } // End of 'for' statement } + } else if sensor.SensorType == "FLX" { + // Sanity checks + if sensor.Flex == nil { + err = errors.New("flex parameter shall be present") + log.Error("OneM2M_create: ", err.Error()) + return sensorResp, err + } else if _, ok := sensor.Flex["type"]; !ok { + err = errors.New("'type' entry is required") + log.Error("OneM2M_create: ", err.Error()) + return sensorResp, err + } else if _, ok := sensor.Flex["type"].(string); !ok { + err = errors.New("'type' entry is required") + log.Error("OneM2M_create: ", err.Error()) + return sensorResp, err + } else if _, ok := sensor.Flex["cnd"]; !ok { + err = errors.New("'cnd' entry is required") + log.Error("OneM2M_create: ", err.Error()) + return sensorResp, err + } else if _, ok := sensor.Flex["cnd"].(string); !ok { + err = errors.New("'cnd' entry is required") + log.Error("OneM2M_create: ", err.Error()) + return sensorResp, err + } + k := sensor.Flex["type"].(string) + bodyMap[k] = make(map[string]interface{}, 0) + bodyMap[k]["rn"] = sensor.SensorIdentifier + for i, v := range sensor.Flex { + if i == "type" { + continue // skip it + } + bodyMap[k][i] = v + } // End of 'for' statement } else { err = errors.New("OneM2M_create: Invalid type") log.Error("OneM2M_create: ", err.Error()) @@ -496,6 +542,8 @@ func (tm *SssMgr) OneM2M_create(sensor SensorDiscoveryInfo, path string) (sensor ctx.ty = 3 } else if sensor.SensorType == "CIN" { ctx.ty = 4 + } else if sensor.SensorType == "FLX" { + ctx.ty = 28 } else { err = errors.New("OneM2M_create: Invalid type") log.Error("send: ", err.Error()) @@ -510,7 +558,13 @@ func (tm *SssMgr) OneM2M_create(sensor SensorDiscoveryInfo, path string) (sensor log.Debug("OneM2M_create: resp: ", resp) log.Debug("OneM2M_create: TypeOf(resp): ", reflect.TypeOf(resp)) if _, ok := resp.(map[string]interface{}); !ok { - log.Error("OneM2M_create: Interface not available") + err = errors.New("Interface not available") + log.Error("OneM2M_create: ", err.Error()) + return sensorResp, err + } + if val, ok := resp.(map[string]interface{})["m2m:dbg"]; ok { + err = errors.New(val.(string)) + log.Error("OneM2M_create: ", err.Error()) return sensorResp, err } @@ -519,6 +573,7 @@ func (tm *SssMgr) OneM2M_create(sensor SensorDiscoveryInfo, path string) (sensor sensorResp.SensorType = sensor.SensorType sensorResp.IotPlatformId = sensor.IotPlatformId sensorResp.SensorPosition = sensor.SensorPosition + sensorResp.Flex = sensor.Flex sensorResp, err = tm.oneM2M_deserialize(sensorResp, resp.(map[string]interface{})) if err != nil { log.Error("OneM2M_create: ", err.Error()) @@ -722,9 +777,13 @@ func (tm *SssMgr) OneM2M_subscribe(iotPlatformId string, path string) (subscript var bodyMap = map[string]map[string]interface{}{} bodyMap["m2m:sub"] = make(map[string]interface{}, 0) net := make(map[string][]int) - net["net"] = []int{2, 3, 4} + net["net"] = []int{1, 2, 3, 4} bodyMap["m2m:sub"]["enc"] = net - bodyMap["m2m:sub"]["nu"] = []string{"http://172.29.10.52:31122/"} // FIXME FSCOM The URI of the listener + if tm.bindingProtocol == "MQTT" { + bodyMap["m2m:sub"]["nu"] = []string{"mqtt://172.29.10.56:1883"} // FIXME FSCOM The URI of the listener + } else { + bodyMap["m2m:sub"]["nu"] = []string{"http://172.29.10.52:31122/"} // FIXME FSCOM The URI of the listener + } bodyMap["m2m:sub"]["rn"] = uuid.New().String() ctx.body = bodyMap @@ -759,7 +818,7 @@ func (tm *SssMgr) OneM2M_subscribe(iotPlatformId string, path string) (subscript log.Error("OneM2M_subscribe: ", err.Error()) return "", err } - log.Debug("OneM2M_cOneM2M_subscribereate: sensvorResp: ", v) + log.Debug("OneM2M_subscribe: v: ", v) subscriptionListPerSubId[subId] = v @@ -773,28 +832,28 @@ func (tm *SssMgr) OneM2M_subscribe(iotPlatformId string, path string) (subscript return subId, nil } -func (tm *SssMgr) OneM2M_Delete(sensor SensorDiscoveryInfo) (err error) { +func (tm *SssMgr) OneM2M_delete(sensor SensorDiscoveryInfo) (err error) { if profiling { - profilingTimers["OneM2M_Delete"] = time.Now() + profilingTimers["OneM2M_delete"] = time.Now() } - log.Info(">>> OneM2M_Delete: sensor=", sensor) + log.Info(">>> OneM2M_delete: sensor=", sensor) if sensor.SensorIdentifier == "" { - err = errors.New("OneM2M_Delete: Cannot find \"ri\" value") - log.Error("OneM2M_Delete: ", err.Error()) + err = errors.New("OneM2M_delete: Cannot find \"ri\" value") + log.Error("OneM2M_delete: ", err.Error()) return err } if sensor.IotPlatformId == "" { err = errors.New("IotPlatformId fiels shall be set") - log.Error("OneM2M_Delete: ", err.Error()) + log.Error("OneM2M_delete: ", err.Error()) return err } tm.wg.Wait() - log.Info("OneM2M_Delete: After Synchro") + log.Info("OneM2M_delete: After Synchro") // Send it and get the result var ctx = SssMgrBindingProtocolContext{ @@ -811,40 +870,40 @@ func (tm *SssMgr) OneM2M_Delete(sensor SensorDiscoveryInfo) (err error) { } err, _ = protocol.send(ctx) if err != nil { - log.Error("OneM2M_Delete: ", err.Error()) + log.Error("OneM2M_delete: ", err.Error()) return err } if profiling { now := time.Now() - log.Debug("OneM2M_Delete: ", now.Sub(profilingTimers["OneM2M_Delete"])) + log.Debug("OneM2M_delete: ", now.Sub(profilingTimers["OneM2M_delete"])) } return nil } -func (tm *SssMgr) OneM2M_DeleteSub(subId string) (err error) { +func (tm *SssMgr) OneM2M_delete_subscription(subId string) (err error) { if profiling { - profilingTimers["OneM2M_DeleteSub"] = time.Now() + profilingTimers["OneM2M_delete_subscription"] = time.Now() } - log.Info(">>> OneM2M_DeleteSub: sensor=", subId) + log.Info(">>> OneM2M_delete_subscription: sensor=", subId) if subId == "" { err = errors.New("subId fiels shall be set") - log.Error("OneM2M_DeleteSub: ", err.Error()) + log.Error("OneM2M_delete_subscription: ", err.Error()) return err } if _, ok := subscriptionListPerSubId[subId]; !ok { err = errors.New("Unkmown subscription identifier") - log.Error("OneM2M_DeleteSub: ", err.Error()) + log.Error("OneM2M_delete_subscription: ", err.Error()) return err } tm.wg.Wait() - log.Info("OneM2M_DeleteSub: After Synchro") + log.Info("OneM2M_delete_subscription: After Synchro") // Send it and get the result var ctx = SssMgrBindingProtocolContext{ @@ -861,16 +920,16 @@ func (tm *SssMgr) OneM2M_DeleteSub(subId string) (err error) { } err, _ = protocol.send(ctx) if err != nil { - log.Error("OneM2M_DeleteSub: ", err.Error()) + log.Error("OneM2M_delete_subscription: ", err.Error()) return err } delete(subscriptionListPerSubId, subId) - log.Info("OneM2M_DeleteSub: New subscriptionListPerSubId: ", subscriptionListPerSubId) + log.Info("OneM2M_delete_subscription: New subscriptionListPerSubId: ", subscriptionListPerSubId) if profiling { now := time.Now() - log.Debug("OneM2M_DeleteSub: ", now.Sub(profilingTimers["OneM2M_DeleteSub"])) + log.Debug("OneM2M_delete_subscription: ", now.Sub(profilingTimers["OneM2M_delete_subscription"])) } return nil @@ -889,7 +948,7 @@ func (tm *SssMgr) notify(sub map[string]interface{}) { return } if _, ok := sub["nev"].(map[string]interface{}); !ok { - log.Warn("notify: nev entry has unexpected type") + log.Warn("notify: nev entry has an unexpected type") return } if _, ok := sub["sur"]; !ok { @@ -947,10 +1006,35 @@ func (tm *SssMgr) notify(sub map[string]interface{}) { } func (tm *SssMgr) oneM2M_deserialize(sensor SensorDiscoveryInfo, response map[string]interface{}) (sensorResp SensorDiscoveryInfo, err error) { + log.Debug(">>> oneM2M_deserialize: sensor: ", sensor) log.Debug(">>> oneM2M_deserialize: response: ", response) sensorResp = sensor // Same data structure + if sensor.SensorType == "FLX" { // Extract flex specific attributes first + // Sanity checks + if sensor.Flex == nil { + err = errors.New("Wrong 'flex' parameter value") + log.Error("oneM2M_deserialize: ", err.Error()) + return sensorResp, err + } + log.Debug("oneM2M_deserialize: Extract flex specific attributes first") + sensorResp.Flex = make(map[string]interface{}) + s := sensor.Flex["type"].(string) + log.Debug("oneM2M_deserialize: s=", s) + log.Debug("oneM2M_deserialize: response[s]: ", response[s]) + for k, v := range sensor.Flex { + log.Debug("oneM2M_deserialize: Processing k= ", k, ", v= ", v) + if e, ok := response[s].(map[string]interface{})[k]; ok { + log.Debug("oneM2M_deserialize: ", k, " is a flex attribute: ", v) + sensorResp.Flex[k] = e + delete(response[s].(map[string]interface{}), k) + } + } // End of 'for' statement + sensorResp.Flex["type"] = s + log.Debug("oneM2M_deserialize: sensorResp.Flex: ", sensorResp.Flex) + } + for i, m := range response { log.Debug("==> ", i, " value is ", m) if _, ok := m.(map[string]interface{}); !ok { diff --git a/go-packages/meep-sss-mgr/onem2m-mgr_test.go b/go-packages/meep-sss-mgr/onem2m-mgr_test.go index e3b43d099..254dfdcc2 100644 --- a/go-packages/meep-sss-mgr/onem2m-mgr_test.go +++ b/go-packages/meep-sss-mgr/onem2m-mgr_test.go @@ -20,7 +20,7 @@ import ( "fmt" "reflect" "testing" - "time" + //"time" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" ) @@ -34,15 +34,15 @@ const tmNamespace = "sandboxtest" // // Invalid Connector // fmt.Println("Invalid SSS Asset Manager") -// tm, err := NewSssMgr("", tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr("", tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err == nil || tm != nil { // t.Fatalf("Service name not set") // } -// tm, err = NewSssMgr(tmName, tmNamespace, "", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err = NewSssMgr(tmName, tmNamespace, "", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err == nil || tm != nil { // t.Fatalf("Binding protocol not set") // } -// tm, err = NewSssMgr(tmName, tmNamespace, "MQTT", "", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err = NewSssMgr(tmName, tmNamespace, "MQTT", "", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err == nil || tm != nil { // t.Fatalf("Host not set") // } @@ -50,14 +50,14 @@ const tmNamespace = "sandboxtest" // if err == nil || tm != nil { // t.Fatalf("Host id not set") // } -// tm, err = NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "", nil, nil, nil) +// tm, err = NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "", nil, nil, nil) // if err == nil || tm != nil { // t.Fatalf("CSE name not set") // } // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err = NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err = NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -69,7 +69,7 @@ const tmNamespace = "sandboxtest" // tm = nil // fmt.Println("Create valid SSS Asset Manager") -// tm, err = NewSssMgr(tmName, tmNamespace, "REST_HTTP", "172.29.10.56", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err = NewSssMgr(tmName, tmNamespace, "REST_HTTP", "172.29.10.56", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -87,7 +87,7 @@ const tmNamespace = "sandboxtest" // log.MeepTextLogInit(t.Name()) // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -110,7 +110,7 @@ const tmNamespace = "sandboxtest" // log.MeepTextLogInit(t.Name()) // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "", 0, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "", 0, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -136,7 +136,7 @@ const tmNamespace = "sandboxtest" // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -170,7 +170,7 @@ const tmNamespace = "sandboxtest" // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -179,7 +179,7 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "12345", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // new_sensor, err := tm.OneM2M_create(sensor, "") // if err != nil { @@ -191,7 +191,7 @@ const tmNamespace = "sandboxtest" // t.Fatalf("Failed to validate AE content") // } -// _ = tm.OneM2M_Delete(new_sensor) +// _ = tm.OneM2M_delete(new_sensor) // // Cleanup // err = tm.DeleteSssMgr() @@ -207,7 +207,7 @@ const tmNamespace = "sandboxtest" // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -216,7 +216,7 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "CMyAE", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // new_sensor_ae, err := tm.OneM2M_create(sensor_ae, "") // if err != nil { @@ -232,7 +232,7 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "CMyCNT", // SensorType: "CNT", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // // sensor_cnt.SensorCharacteristicList = make([]SensorCharacteristic, 1) // // sensor_cnt.SensorCharacteristicList[0] = SensorCharacteristic{CharacteristicName: "con", CharacteristicValue: "OFF"} @@ -244,14 +244,14 @@ const tmNamespace = "sandboxtest" // // Verify content // if !validate_sensor_cnt(sensor_cnt, new_sensor_cnt) { -// t.Fatalf("Failed to validate AE content") +// t.Fatalf("Failed to validate CNT content") // } -// err = tm.OneM2M_Delete(new_sensor_cnt) +// err = tm.OneM2M_delete(new_sensor_cnt) // if err != nil { // t.Fatalf("Failed to create new sensor") // } -// err = tm.OneM2M_Delete(new_sensor_ae) +// err = tm.OneM2M_delete(new_sensor_ae) // if err != nil { // t.Fatalf("Failed to create new sensor") // } @@ -264,13 +264,87 @@ const tmNamespace = "sandboxtest" // tm = nil // } +func TestOneM2M_createAE_FLEXHttp(t *testing.T) { + fmt.Println("--- ", t.Name()) + log.MeepTextLogInit(t.Name()) + + // Valid Connector + fmt.Println("Create valid SSS Asset Manager") + tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) + if err != nil || tm == nil { + t.Fatalf("Failed to create SSS Asset Manager") + } + + var sensor_ae = SensorDiscoveryInfo{ + SensorIdentifier: "CMyAE", + SensorType: "AE", + SensorPosition: nil, + IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", + } + new_sensor_ae, err := tm.OneM2M_create(sensor_ae, "") + if err != nil { + t.Fatalf("Failed to create new AE sensor") + } + + // Verify content + if !validate_sensor_ae(sensor_ae, new_sensor_ae) { + t.Fatalf("Failed to validate AE content") + } + + var sensor_flex = SensorDiscoveryInfo{ + SensorIdentifier: "CMyFLX", + SensorType: "FLX", + SensorPosition: nil, + IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", + } + sensor_flex.Flex = make(map[string]interface{}, 0) + sensor_flex.Flex["type"] = "cod:color" + sensor_flex.Flex["cnd"] = "org.onem2m.common.moduleclass.colour" + sensor_flex.Flex["red"] = 20 + sensor_flex.Flex["green"] = 20 + sensor_flex.Flex["blue"] = 20 + sensorPath := new_sensor_ae.SensorIdentifier + new_sensor_flex, err := tm.OneM2M_create(sensor_flex, sensorPath) + if err != nil { + t.Fatalf("Failed to create new CNT sensor") + } + + // Verify content + if !validate_sensor_flex(sensor_flex, new_sensor_flex) { + t.Fatalf("Failed to validate FLEX content") + } + + sensors, err := tm.SensorDiscoveryInfoAll() + if err != nil { + t.Fatalf(err.Error()) + } + fmt.Println("len=", len(sensors)) + fmt.Println("sensors", sensors) + + err = tm.OneM2M_delete(new_sensor_flex) + if err != nil { + t.Fatalf("Failed to create new sensor") + } + err = tm.OneM2M_delete(new_sensor_ae) + if err != nil { + t.Fatalf("Failed to create new sensor") + } + + // Cleanup + err = tm.DeleteSssMgr() + if err != nil { + t.Fatalf("Failed to cleanup SSS Asset Manager") + } + tm = nil +} + // func TestOneM2M_createAE_CNT_CNIHttp(t *testing.T) { // fmt.Println("--- ", t.Name()) // log.MeepTextLogInit(t.Name()) // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -279,7 +353,7 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "CMyAE", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // new_sensor_ae, err := tm.OneM2M_create(sensor_ae, "") // if err != nil { @@ -295,7 +369,7 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "CMyCNT", // SensorType: "CNT", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // sensorPath := new_sensor_ae.SensorIdentifier // new_sensor_cnt, err := tm.OneM2M_create(sensor_cnt, sensorPath) @@ -312,7 +386,7 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "CMyCNI", // SensorType: "CIN", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // sensor_cin.SensorCharacteristicList = make([]SensorCharacteristic, 1) // sensor_cin.SensorCharacteristicList[0] = SensorCharacteristic{CharacteristicName: "con", CharacteristicValue: "OFF"} @@ -327,15 +401,15 @@ const tmNamespace = "sandboxtest" // t.Fatalf("Failed to validate CIN content") // } -// err = tm.OneM2M_Delete(new_sensor_cin) +// err = tm.OneM2M_delete(new_sensor_cin) // if err != nil { // t.Fatalf("Failed to create new sensor") // } -// err = tm.OneM2M_Delete(new_sensor_cnt) +// err = tm.OneM2M_delete(new_sensor_cnt) // if err != nil { // t.Fatalf("Failed to create new sensor") // } -// err = tm.OneM2M_Delete(new_sensor_ae) +// err = tm.OneM2M_delete(new_sensor_ae) // if err != nil { // t.Fatalf("Failed to create new sensor") // } @@ -354,7 +428,7 @@ const tmNamespace = "sandboxtest" // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -363,14 +437,14 @@ const tmNamespace = "sandboxtest" // SensorIdentifier: "12345", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // sensor, err := oneM2M_create(tm, new_sensor, "") // if err != nil { // t.Fatalf("Failed to create new sensor: " + err.Error()) // } -// err = tm.OneM2M_Delete(sensor) +// err = tm.OneM2M_delete(sensor) // if err != nil { // t.Fatalf("Failed to create new sensor: " + err.Error()) // } @@ -389,7 +463,7 @@ const tmNamespace = "sandboxtest" // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -423,9 +497,9 @@ const tmNamespace = "sandboxtest" // t.Fatalf("Failed to validate CIN content") // } -// _ = tm.OneM2M_Delete(received_sensors["CIN"]) -// _ = tm.OneM2M_Delete(received_sensors["CNT"]) -// _ = tm.OneM2M_Delete(received_sensors["AE"]) +// _ = tm.OneM2M_delete(received_sensors["CIN"]) +// _ = tm.OneM2M_delete(received_sensors["CNT"]) +// _ = tm.OneM2M_delete(received_sensors["AE"]) // // Cleanup // err = tm.DeleteSssMgr() @@ -441,7 +515,7 @@ const tmNamespace = "sandboxtest" // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -482,9 +556,9 @@ const tmNamespace = "sandboxtest" // t.Fatalf("Failed to validate AE content") // } -// _ = tm.OneM2M_Delete(received_sensors["CIN"]) -// _ = tm.OneM2M_Delete(received_sensors["CNT"]) -// _ = tm.OneM2M_Delete(received_sensors["AE"]) +// _ = tm.OneM2M_delete(received_sensors["CIN"]) +// _ = tm.OneM2M_delete(received_sensors["CNT"]) +// _ = tm.OneM2M_delete(received_sensors["AE"]) // // Cleanup // err = tm.DeleteSssMgr() @@ -494,67 +568,67 @@ const tmNamespace = "sandboxtest" // tm = nil // } -func TestOneM2M_subscribeHttp(t *testing.T) { - fmt.Println("--- ", t.Name()) - log.MeepTextLogInit(t.Name()) +// func TestOneM2M_subscribeHttp(t *testing.T) { +// fmt.Println("--- ", t.Name()) +// log.MeepTextLogInit(t.Name()) - // Valid Connector - fmt.Println("Create valid SSS Asset Manager") - tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "7feaadbb0400", "laboai-acme-ic-cse", discoveryNotify, statusNotify, dataNotify) - if err != nil || tm == nil { - t.Fatalf("Failed to create SSS Asset Manager") - } +// // Valid Connector +// fmt.Println("Create valid SSS Asset Manager") +// tm, err := NewSssMgr(tmName, tmNamespace, "REST_HTTP", "lab-oai.etsi.org", 31110, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", discoveryNotify, statusNotify, dataNotify) +// if err != nil || tm == nil { +// t.Fatalf("Failed to create SSS Asset Manager") +// } - _, received_sensors, err := oneM2M_createAE_CNT_CIN(tm) - if err != nil { - t.Fatalf("Failed to create sensors") - } +// _, received_sensors, err := oneM2M_createAE_CNT_CIN(tm) +// if err != nil { +// t.Fatalf("Failed to create sensors") +// } - subscriptionMap := make(map[string]interface{}) - subId, err := tm.OneM2M_subscribe(received_sensors["AE"].IotPlatformId, received_sensors["AE"].SensorIdentifier) - if err != nil { - t.Fatalf("Failed to subscribe") - } - fmt.Println("subId=" + subId) - subscriptionMap[subId] = received_sensors["AE"] +// subscriptionMap := make(map[string]interface{}) +// subId, err := tm.OneM2M_subscribe(received_sensors["AE"].IotPlatformId, received_sensors["AE"].SensorIdentifier) +// if err != nil { +// t.Fatalf("Failed to subscribe") +// } +// fmt.Println("subId=" + subId) +// subscriptionMap[subId] = received_sensors["AE"] - subId, err = tm.OneM2M_subscribe(received_sensors["CNT"].IotPlatformId, received_sensors["CNT"].SensorIdentifier) - if err != nil { - t.Fatalf("Failed to subscribe") - } - fmt.Println("subId=" + subId) - subscriptionMap[subId] = received_sensors["CNT"] +// subId, err = tm.OneM2M_subscribe(received_sensors["CNT"].IotPlatformId, received_sensors["CNT"].SensorIdentifier) +// if err != nil { +// t.Fatalf("Failed to subscribe") +// } +// fmt.Println("subId=" + subId) +// subscriptionMap[subId] = received_sensors["CNT"] - fmt.Println("len(subscriptionMap)=" + fmt.Sprint(len(subscriptionMap))) +// fmt.Println("len(subscriptionMap)=" + fmt.Sprint(len(subscriptionMap))) - fmt.Println("You have 120 seconds to trigger subscriptions") - time.Sleep(time.Duration(120) * time.Second) +// fmt.Println("You have 120 seconds to trigger subscriptions") +// time.Sleep(time.Duration(120) * time.Second) - for k := range subscriptionMap { - err = tm.OneM2M_DeleteSub(k) - if err != nil { - t.Fatalf("Failed to cancel subscription") - } - } // End of 'for' statement +// for k := range subscriptionMap { +// err = tm.OneM2M_delete_subscription(k) +// if err != nil { +// t.Fatalf("Failed to cancel subscription") +// } +// } // End of 'for' statement - _ = tm.OneM2M_Delete(received_sensors["CIN"]) - _ = tm.OneM2M_Delete(received_sensors["CNT"]) - _ = tm.OneM2M_Delete(received_sensors["AE"]) +// _ = tm.OneM2M_delete(received_sensors["CIN"]) +// _ = tm.OneM2M_delete(received_sensors["CNT"]) +// _ = tm.OneM2M_delete(received_sensors["AE"]) - // Cleanup - err = tm.DeleteSssMgr() - if err != nil { - t.Fatalf("Failed to cleanup SSS Asset Manager") - } - tm = nil -} +// // Cleanup +// err = tm.DeleteSssMgr() +// if err != nil { +// t.Fatalf("Failed to cleanup SSS Asset Manager") +// } +// tm = nil +// } // func TestPopulateDevicesPerIotPlatformsMqtt(t *testing.T) { // fmt.Println("--- ", t.Name()) // log.MeepTextLogInit(t.Name()) // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -576,7 +650,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -605,7 +679,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -639,7 +713,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -648,7 +722,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "12345", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // new_sensor, err := tm.OneM2M_create(sensor, "") // if err != nil { @@ -660,7 +734,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // t.Fatalf("Failed to validate AE content") // } -// _ = tm.OneM2M_Delete(new_sensor) +// _ = tm.OneM2M_delete(new_sensor) // // Cleanup // err = tm.DeleteSssMgr() @@ -676,7 +750,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -685,7 +759,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "CMyAE", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // new_sensor_ae, err := tm.OneM2M_create(sensor_ae, "") // if err != nil { @@ -701,7 +775,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "CMyCNT", // SensorType: "CNT", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // // sensor_cnt.SensorCharacteristicList = make([]SensorCharacteristic, 1) // // sensor_cnt.SensorCharacteristicList[0] = SensorCharacteristic{CharacteristicName: "con", CharacteristicValue: "OFF"} @@ -716,11 +790,11 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // t.Fatalf("Failed to validate CNT content") // } -// err = tm.OneM2M_Delete(new_sensor_cnt) +// err = tm.OneM2M_delete(new_sensor_cnt) // if err != nil { // t.Fatalf("Failed to create new sensor") // } -// err = tm.OneM2M_Delete(new_sensor_ae) +// err = tm.OneM2M_delete(new_sensor_ae) // if err != nil { // t.Fatalf("Failed to create new sensor") // } @@ -739,7 +813,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -748,7 +822,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "CMyAE", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // new_sensor_ae, err := tm.OneM2M_create(sensor_ae, "") // if err != nil { @@ -764,7 +838,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "CMyCNT", // SensorType: "CNT", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // sensorPath := new_sensor_ae.SensorIdentifier // new_sensor_cnt, err := tm.OneM2M_create(sensor_cnt, sensorPath) @@ -781,7 +855,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "CMyCNI", // SensorType: "CIN", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // sensor_cin.SensorCharacteristicList = make([]SensorCharacteristic, 1) // sensor_cin.SensorCharacteristicList[0] = SensorCharacteristic{CharacteristicName: "con", CharacteristicValue: "OFF"} @@ -800,15 +874,15 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // t.Fatalf("received_sensor.SensorCharacteristicList shall not be empty") // } -// err = tm.OneM2M_Delete(new_sensor_cin) +// err = tm.OneM2M_delete(new_sensor_cin) // if err != nil { // t.Fatalf("Failed to create new sensor") // } -// err = tm.OneM2M_Delete(new_sensor_cnt) +// err = tm.OneM2M_delete(new_sensor_cnt) // if err != nil { // t.Fatalf("Failed to create new sensor") // } -// err = tm.OneM2M_Delete(new_sensor_ae) +// err = tm.OneM2M_delete(new_sensor_ae) // if err != nil { // t.Fatalf("Failed to create new sensor") // } @@ -827,7 +901,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -836,14 +910,14 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // SensorIdentifier: "12345", // SensorType: "AE", // SensorPosition: nil, -// IotPlatformId: "7feaadbb0400", +// IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", // } // sensor, err := oneM2M_create(tm, new_sensor, "") // if err != nil { // t.Fatalf("Failed to create new sensor: " + err.Error()) // } -// err = tm.OneM2M_Delete(sensor) +// err = tm.OneM2M_delete(sensor) // if err != nil { // t.Fatalf("Failed to create new sensor: " + err.Error()) // } @@ -862,7 +936,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -896,9 +970,9 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // t.Fatalf("Failed to validate CIN content") // } -// _ = tm.OneM2M_Delete(received_sensors["CIN"]) -// _ = tm.OneM2M_Delete(received_sensors["CNT"]) -// _ = tm.OneM2M_Delete(received_sensors["AE"]) +// _ = tm.OneM2M_delete(received_sensors["CIN"]) +// _ = tm.OneM2M_delete(received_sensors["CNT"]) +// _ = tm.OneM2M_delete(received_sensors["AE"]) // // Cleanup // err = tm.DeleteSssMgr() @@ -914,7 +988,7 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", nil, nil, nil) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } @@ -955,9 +1029,9 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // t.Fatalf("Failed to validate AE content") // } -// _ = tm.OneM2M_Delete(received_sensors["CIN"]) -// _ = tm.OneM2M_Delete(received_sensors["CNT"]) -// _ = tm.OneM2M_Delete(received_sensors["AE"]) +// _ = tm.OneM2M_delete(received_sensors["CIN"]) +// _ = tm.OneM2M_delete(received_sensors["CNT"]) +// _ = tm.OneM2M_delete(received_sensors["AE"]) // // Cleanup // err = tm.DeleteSssMgr() @@ -966,26 +1040,59 @@ func TestOneM2M_subscribeHttp(t *testing.T) { // } // tm = nil // } - -// func TestVaidateOneM2MNotificationServer(t *testing.T) { +// func TestOneM2M_subscribeMQTT(t *testing.T) { // fmt.Println("--- ", t.Name()) // log.MeepTextLogInit(t.Name()) // // Valid Connector // fmt.Println("Create valid SSS Asset Manager") -// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "MQTT", "172.29.10.56", 1883, "7feaadbb0400", "laboai-acme-ic-cse", nil, nil, nil) +// tm, err := NewSssMgr(tmName, tmNamespace, "MQTT", "172.29.10.56", 1883, "0a692154-0f93-11f0-b554-df2f6a756f6a", "laboai-acme-ic-cse", discoveryNotify, statusNotify, dataNotify) // if err != nil || tm == nil { // t.Fatalf("Failed to create SSS Asset Manager") // } -// tm.init() -// fmt.Println("Waiting for 2 minutes to do curl request: curl -v http://mec-platform.etsi.org:31122/sbxykqjr17/mep1/sens/v1 ") +// _, received_sensors, err := oneM2M_createAE_CNT_CIN(tm) +// if err != nil { +// t.Fatalf("Failed to create sensors") +// } + +// subscriptionMap := make(map[string]interface{}) +// subId, err := tm.OneM2M_subscribe(received_sensors["AE"].IotPlatformId, received_sensors["AE"].SensorIdentifier) +// if err != nil { +// t.Fatalf("Failed to subscribe") +// } +// fmt.Println("subId=" + subId) +// subscriptionMap[subId] = received_sensors["AE"] + +// subId, err = tm.OneM2M_subscribe(received_sensors["CNT"].IotPlatformId, received_sensors["CNT"].SensorIdentifier) +// if err != nil { +// t.Fatalf("Failed to subscribe") +// } +// fmt.Println("subId=" + subId) +// subscriptionMap[subId] = received_sensors["CNT"] + +// fmt.Println("len(subscriptionMap)=" + fmt.Sprint(len(subscriptionMap))) + +// fmt.Println("You have 120 seconds to trigger subscriptions") +// time.Sleep(time.Duration(120) * time.Second) + +// for k := range subscriptionMap { +// err = tm.OneM2M_delete_subscription(k) +// if err != nil { +// t.Fatalf("Failed to cancel subscription") +// } +// } // End of 'for' statement + +// _ = tm.OneM2M_delete(received_sensors["CIN"]) +// _ = tm.OneM2M_delete(received_sensors["CNT"]) +// _ = tm.OneM2M_delete(received_sensors["AE"]) // // Cleanup // err = tm.DeleteSssMgr() // if err != nil { // t.Fatalf("Failed to cleanup SSS Asset Manager") // } +// tm = nil // } func oneM2M_create(tm *SssMgr, sensor SensorDiscoveryInfo, path string) (sensorResp SensorDiscoveryInfo, err error) { @@ -1005,7 +1112,7 @@ func oneM2M_createAE_CNT_CIN(tm *SssMgr) (sensors map[string]SensorDiscoveryInfo SensorIdentifier: "CMyAE", SensorType: "AE", SensorPosition: nil, - IotPlatformId: "7feaadbb0400", + IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", } sensors[sensor_ae.SensorType] = sensor_ae new_sensor_ae, err := oneM2M_create(tm, sensor_ae, "") @@ -1018,7 +1125,7 @@ func oneM2M_createAE_CNT_CIN(tm *SssMgr) (sensors map[string]SensorDiscoveryInfo SensorIdentifier: "CMyCNT", SensorType: "CNT", SensorPosition: nil, - IotPlatformId: "7feaadbb0400", + IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", } sensorPath := new_sensor_ae.SensorIdentifier sensors[sensor_cnt.SensorType] = sensor_cnt @@ -1032,7 +1139,7 @@ func oneM2M_createAE_CNT_CIN(tm *SssMgr) (sensors map[string]SensorDiscoveryInfo SensorIdentifier: "CMyCNI", SensorType: "CIN", SensorPosition: nil, - IotPlatformId: "7feaadbb0400", + IotPlatformId: "0a692154-0f93-11f0-b554-df2f6a756f6a", } sensor_cin.SensorCharacteristicList = make([]SensorCharacteristic, 1) sensor_cin.SensorCharacteristicList[0] = SensorCharacteristic{CharacteristicName: "con", CharacteristicValue: "OFF"} @@ -1122,7 +1229,7 @@ func validate_sensor_cnt(expected_sensor SensorDiscoveryInfo, received_sensor Se fmt.Println(">>> validate_sensor_cnt: received_sensor: ", received_sensor) if received_sensor.SensorIdentifier == "" { - fmt.Println("validate_sensor_ae.SensorIdentifier shall be set") + fmt.Println("validate_sensor_cnt.SensorIdentifier shall be set") return false } if received_sensor.SensorType != received_sensor.SensorType { @@ -1207,6 +1314,39 @@ func validate_sensor_cin(expected_sensor SensorDiscoveryInfo, received_sensor Se return true } +func validate_sensor_flex(expected_sensor SensorDiscoveryInfo, received_sensor SensorDiscoveryInfo) bool { + fmt.Println(">>> validate_sensor_flex: expected_sensor: ", expected_sensor) + fmt.Println(">>> validate_sensor_flex: received_sensor: ", received_sensor) + + if received_sensor.SensorIdentifier == "" { + fmt.Println("validate_sensor_flex.SensorIdentifier shall be set") + return false + } + if received_sensor.SensorType != received_sensor.SensorType { + fmt.Println("validate_sensor_flex.SensorType != SensorType") + return false + } + if received_sensor.IotPlatformId != expected_sensor.IotPlatformId { + fmt.Println("validate_sensor_flex.IotPlatformId != IotPlatformId") + return false + } + if expected_sensor.Flex == nil || received_sensor.Flex == nil { + fmt.Println("validate_sensor_flex.Flex != Flex") + return false + } else if len(expected_sensor.Flex) != len(received_sensor.Flex) { + fmt.Println("len(validate_sensor_flex.Flex) != len(Flex)") + return false + } else if expected_sensor.Flex["type"] != received_sensor.Flex["type"] { + fmt.Println("validate_sensor_flex.Flex[type] != Flex[type]") + return false + } else if expected_sensor.Flex["cnd"] != received_sensor.Flex["cnd"] { + fmt.Println("validate_sensor_flex.Flex[cnd] != Flex[cnd]") + return false + } + + return true +} + func discoveryNotify(map[string]interface{}) { log.Debug(">>> discoveryNotify") diff --git a/go-packages/meep-vis-traffic-mgr/mqtt.go b/go-packages/meep-vis-traffic-mgr/mqtt.go index 07cec8eb2..43c6832ad 100644 --- a/go-packages/meep-vis-traffic-mgr/mqtt.go +++ b/go-packages/meep-vis-traffic-mgr/mqtt.go @@ -43,7 +43,7 @@ func onMessageReceived(client mqtt.Client, msg mqtt.Message) { _v2x_notify(msg.Payload(), 16, 2, "ETSI", nil, nil) } } else { - log.Info("onMessageReceived: null pointer for the callbacl") + log.Info("onMessageReceived: null pointer for the callback") } }() } -- GitLab From f3192fa250cb48285600d501cfdc3e40cf77302c Mon Sep 17 00:00:00 2001 From: garciay Date: Tue, 22 Apr 2025 11:08:54 +0200 Subject: [PATCH 002/108] Add MEC 046 example --- examples/demo9/README.md | 1 + examples/demo9/golang/Dockerfile | 26 + examples/demo9/golang/README.md | 145 + examples/demo9/golang/app_instance.yaml | 18 + examples/demo9/golang/build-demo9.sh | 22 + examples/demo9/golang/build_test.sh | 16 + examples/demo9/golang/client/README.md | 84 + examples/demo9/golang/client/api/swagger.yaml | 1521 +++++++ .../demo9/golang/client/api_authorization.go | 264 ++ .../client/api_sandbox_app_instances.go | 270 ++ .../client/api_sandbox_logs_subscriptions.go | 182 + .../golang/client/api_sandbox_mec_services.go | 112 + .../client/api_sandbox_network_scenarios.go | 344 ++ .../client/api_sandbox_ue_controller.go | 184 + examples/demo9/golang/client/client.go | 490 +++ examples/demo9/golang/client/configuration.go | 72 + .../golang/client/docs/ApplicationInfo.md | 13 + .../golang/client/docs/AuthorizationApi.md | 65 + .../client/docs/CellularDomainConfig.md | 11 + .../golang/client/docs/CellularPoaConfig.md | 9 + .../golang/client/docs/ConnectivityConfig.md | 9 + .../demo9/golang/client/docs/CpuConfig.md | 10 + .../demo9/golang/client/docs/D2dConfig.md | 10 + .../demo9/golang/client/docs/Deployment.md | 18 + examples/demo9/golang/client/docs/DnConfig.md | 11 + examples/demo9/golang/client/docs/Domain.md | 20 + .../demo9/golang/client/docs/EgressService.md | 13 + .../golang/client/docs/ExternalConfig.md | 10 + examples/demo9/golang/client/docs/GeoData.md | 15 + .../demo9/golang/client/docs/GpuConfig.md | 10 + .../golang/client/docs/IngressService.md | 12 + .../demo9/golang/client/docs/LineString.md | 10 + .../demo9/golang/client/docs/MemoryConfig.md | 10 + .../client/docs/NetworkCharacteristics.md | 15 + .../golang/client/docs/NetworkLocation.md | 24 + .../golang/client/docs/PhysicalLocation.md | 27 + .../demo9/golang/client/docs/Poa4GConfig.md | 9 + .../demo9/golang/client/docs/Poa5GConfig.md | 9 + .../demo9/golang/client/docs/PoaWifiConfig.md | 9 + examples/demo9/golang/client/docs/Point.md | 10 + .../golang/client/docs/ProblemDetails.md | 13 + examples/demo9/golang/client/docs/Process.md | 33 + examples/demo9/golang/client/docs/Sandbox.md | 9 + .../golang/client/docs/SandboxAppInstances.md | 9 + .../client/docs/SandboxAppInstancesApi.md | 96 + .../client/docs/SandboxLogsSubscriptions.md | 10 + .../docs/SandboxLogsSubscriptionsApi.md | 66 + .../client/docs/SandboxMECServicesApi.md | 36 + .../golang/client/docs/SandboxMecServices.md | 10 + .../client/docs/SandboxNetworkScenario.md | 9 + .../client/docs/SandboxNetworkScenariosApi.md | 126 + .../client/docs/SandboxUEControllerApi.md | 67 + examples/demo9/golang/client/docs/Scenario.md | 14 + .../golang/client/docs/ScenarioConfig.md | 10 + .../demo9/golang/client/docs/ServiceConfig.md | 11 + .../demo9/golang/client/docs/ServicePort.md | 11 + examples/demo9/golang/client/docs/Ue.md | 9 + examples/demo9/golang/client/docs/Zone.md | 27 + examples/demo9/golang/client/git_push.sh | 52 + .../golang/client/model_application_info.go | 24 + .../client/model_cellular_domain_config.go | 20 + .../client/model_cellular_poa_config.go | 16 + .../client/model_connectivity_config.go | 15 + .../demo9/golang/client/model_cpu_config.go | 18 + .../demo9/golang/client/model_d2d_config.go | 18 + .../demo9/golang/client/model_deployment.go | 30 + .../demo9/golang/client/model_dn_config.go | 20 + examples/demo9/golang/client/model_domain.go | 35 + .../golang/client/model_egress_service.go | 24 + .../golang/client/model_external_config.go | 16 + .../demo9/golang/client/model_geo_data.go | 24 + .../demo9/golang/client/model_gpu_config.go | 18 + .../golang/client/model_ingress_service.go | 22 + .../demo9/golang/client/model_line_string.go | 18 + .../golang/client/model_memory_config.go | 18 + .../demo9/golang/client/model_namespace.go | 16 + .../client/model_network_characteristics.go | 28 + .../golang/client/model_network_location.go | 39 + examples/demo9/golang/client/model_oauth.go | 17 + .../golang/client/model_physical_location.go | 47 + .../golang/client/model_poa4_g_config.go | 16 + .../golang/client/model_poa5_g_config.go | 16 + .../golang/client/model_poa_wifi_config.go | 16 + examples/demo9/golang/client/model_point.go | 18 + .../golang/client/model_problem_details.go | 24 + examples/demo9/golang/client/model_process.go | 58 + .../client/model_sandbox_app_instances.go | 15 + .../model_sandbox_logs_subscriptions.go | 17 + .../client/model_sandbox_mec_services.go | 17 + .../client/model_sandbox_network_scenario.go | 15 + .../demo9/golang/client/model_scenario.go | 24 + .../golang/client/model_scenario_config.go | 18 + .../golang/client/model_service_config.go | 19 + .../demo9/golang/client/model_service_port.go | 20 + examples/demo9/golang/client/model_ue.go | 17 + examples/demo9/golang/client/model_zone.go | 50 + examples/demo9/golang/client/response.go | 43 + examples/demo9/golang/docker_build.sh | 16 + examples/demo9/golang/docker_run.sh | 10 + examples/demo9/golang/dockerize.sh | 30 + examples/demo9/golang/entrypoint.sh | 12 + examples/demo9/golang/git_push.sh | 52 + examples/demo9/golang/go.mod | 23 + examples/demo9/golang/go.sum | 1608 +++++++ examples/demo9/golang/main.go | 1993 +++++++++ examples/demo9/golang/routers.go | 98 + examples/demo9/golang/run.sh | 9 + examples/demo9/python/README.md | 6 + examples/demo9/python/mecapp/.gitignore | 64 + .../python/mecapp/.swagger-codegen-ignore | 23 + .../python/mecapp/.swagger-codegen/VERSION | 1 + examples/demo9/python/mecapp/.travis.yml | 13 + examples/demo9/python/mecapp/README.md | 143 + .../python/mecapp/docs/ApplicationInfo.md | 13 + .../python/mecapp/docs/AuthorizationApi.md | 104 + .../mecapp/docs/CellularDomainConfig.md | 11 + .../python/mecapp/docs/CellularPoaConfig.md | 9 + .../python/mecapp/docs/ConnectivityConfig.md | 9 + .../demo9/python/mecapp/docs/CpuConfig.md | 10 + .../demo9/python/mecapp/docs/D2dConfig.md | 10 + examples/demo9/python/mecapp/docs/DNConfig.md | 11 + .../demo9/python/mecapp/docs/Deployment.md | 18 + examples/demo9/python/mecapp/docs/Domain.md | 20 + .../demo9/python/mecapp/docs/EgressService.md | 13 + .../python/mecapp/docs/ExternalConfig.md | 10 + examples/demo9/python/mecapp/docs/GeoData.md | 15 + .../demo9/python/mecapp/docs/GpuConfig.md | 10 + .../python/mecapp/docs/IngressService.md | 12 + .../demo9/python/mecapp/docs/LineString.md | 10 + .../demo9/python/mecapp/docs/MemoryConfig.md | 10 + .../mecapp/docs/NetworkCharacteristics.md | 15 + .../python/mecapp/docs/NetworkLocation.md | 24 + .../python/mecapp/docs/PhysicalLocation.md | 27 + .../demo9/python/mecapp/docs/Poa4GConfig.md | 9 + .../demo9/python/mecapp/docs/Poa5GConfig.md | 9 + .../demo9/python/mecapp/docs/PoaWifiConfig.md | 9 + examples/demo9/python/mecapp/docs/Point.md | 10 + .../python/mecapp/docs/ProblemDetails.md | 13 + examples/demo9/python/mecapp/docs/Process.md | 33 + examples/demo9/python/mecapp/docs/Sandbox.md | 9 + .../python/mecapp/docs/SandboxAppInstances.md | 9 + .../mecapp/docs/SandboxAppInstancesApi.md | 157 + .../mecapp/docs/SandboxLogsSubscriptions.md | 10 + .../docs/SandboxLogsSubscriptionsApi.md | 106 + .../mecapp/docs/SandboxMECServicesApi.md | 56 + .../python/mecapp/docs/SandboxMecServices.md | 10 + .../mecapp/docs/SandboxNetworkScenario.md | 9 + .../mecapp/docs/SandboxNetworkScenariosApi.md | 207 + .../mecapp/docs/SandboxUEControllerApi.md | 108 + examples/demo9/python/mecapp/docs/Scenario.md | 14 + .../python/mecapp/docs/ScenarioConfig.md | 10 + .../demo9/python/mecapp/docs/ServiceConfig.md | 11 + .../demo9/python/mecapp/docs/ServicePort.md | 11 + examples/demo9/python/mecapp/docs/UE.md | 9 + examples/demo9/python/mecapp/docs/Zone.md | 27 + examples/demo9/python/mecapp/git_push.sh | 52 + examples/demo9/python/mecapp/requirements.txt | 5 + examples/demo9/python/mecapp/setup.py | 39 + .../python/mecapp/swagger_client/__init__.py | 64 + .../mecapp/swagger_client/api/__init__.py | 11 + .../swagger_client/api/authorization_api.py | 314 ++ .../api/sandbox_app_instances_api.py | 334 ++ .../api/sandbox_logs_subscriptions_api.py | 227 + .../api/sandbox_mec_services_api.py | 128 + .../api/sandbox_network_scenarios_api.py | 429 ++ .../api/sandbox_ue_controller_api.py | 235 + .../mecapp/swagger_client/api_client.py | 634 +++ .../mecapp/swagger_client/configuration.py | 244 ++ .../mecapp/swagger_client/models/__init__.py | 53 + .../swagger_client/models/application_info.py | 232 + .../models/cellular_domain_config.py | 168 + .../models/cellular_poa_config.py | 112 + .../models/connectivity_config.py | 118 + .../swagger_client/models/cpu_config.py | 140 + .../swagger_client/models/d2d_config.py | 140 + .../swagger_client/models/deployment.py | 356 ++ .../mecapp/swagger_client/models/dn_config.py | 168 + .../mecapp/swagger_client/models/domain.py | 420 ++ .../swagger_client/models/egress_service.py | 224 + .../swagger_client/models/external_config.py | 136 + .../mecapp/swagger_client/models/geo_data.py | 278 ++ .../swagger_client/models/gpu_config.py | 140 + .../swagger_client/models/ingress_service.py | 196 + .../swagger_client/models/line_string.py | 147 + .../swagger_client/models/memory_config.py | 140 + .../mecapp/swagger_client/models/namespace.py | 112 + .../models/network_characteristics.py | 286 ++ .../swagger_client/models/network_location.py | 524 +++ .../mecapp/swagger_client/models/oauth.py | 140 + .../models/physical_location.py | 612 +++ .../swagger_client/models/poa4_g_config.py | 112 + .../swagger_client/models/poa5_g_config.py | 112 + .../swagger_client/models/poa_wifi_config.py | 112 + .../mecapp/swagger_client/models/point.py | 147 + .../swagger_client/models/problem_details.py | 226 + .../mecapp/swagger_client/models/process.py | 778 ++++ .../mecapp/swagger_client/models/sandbox.py | 112 + .../models/sandbox_app_instances.py | 113 + .../models/sandbox_logs_subscriptions.py | 141 + .../models/sandbox_mec_services.py | 141 + .../models/sandbox_network_scenario.py | 113 + .../mecapp/swagger_client/models/scenario.py | 248 ++ .../swagger_client/models/scenario_config.py | 140 + .../swagger_client/models/service_config.py | 166 + .../swagger_client/models/service_port.py | 168 + .../python/mecapp/swagger_client/models/ue.py | 113 + .../mecapp/swagger_client/models/zone.py | 618 +++ .../python/mecapp/swagger_client/rest.py | 317 ++ .../demo9/python/mecapp/test-requirements.txt | 5 + examples/demo9/python/mecapp/test/__init__.py | 1 + .../mecapp/test/test_application_info.py | 39 + .../mecapp/test/test_authorization_api.py | 47 + .../test/test_cellular_domain_config.py | 39 + .../mecapp/test/test_cellular_poa_config.py | 39 + .../mecapp/test/test_connectivity_config.py | 39 + .../python/mecapp/test/test_cpu_config.py | 39 + .../python/mecapp/test/test_d2d_config.py | 39 + .../python/mecapp/test/test_deployment.py | 39 + .../python/mecapp/test/test_dn_config.py | 39 + .../demo9/python/mecapp/test/test_domain.py | 39 + .../python/mecapp/test/test_egress_service.py | 39 + .../mecapp/test/test_external_config.py | 39 + .../demo9/python/mecapp/test/test_geo_data.py | 39 + .../python/mecapp/test/test_gpu_config.py | 39 + .../mecapp/test/test_ingress_service.py | 39 + .../python/mecapp/test/test_line_string.py | 39 + .../python/mecapp/test/test_memory_config.py | 39 + .../test/test_network_characteristics.py | 39 + .../mecapp/test/test_network_location.py | 39 + .../mecapp/test/test_physical_location.py | 39 + .../python/mecapp/test/test_poa4_g_config.py | 39 + .../python/mecapp/test/test_poa5_g_config.py | 39 + .../mecapp/test/test_poa_wifi_config.py | 39 + .../demo9/python/mecapp/test/test_point.py | 39 + .../mecapp/test/test_problem_details.py | 39 + .../demo9/python/mecapp/test/test_process.py | 39 + .../demo9/python/mecapp/test/test_sandbox.py | 39 + .../mecapp/test/test_sandbox_app_instances.py | 39 + .../test/test_sandbox_app_instances_api.py | 54 + .../test/test_sandbox_logs_subscriptions.py | 39 + .../test_sandbox_logs_subscriptions_api.py | 47 + .../mecapp/test/test_sandbox_mec_services.py | 39 + .../test/test_sandbox_mec_services_api.py | 40 + .../test/test_sandbox_network_scenario.py | 39 + .../test_sandbox_network_scenarios_api.py | 61 + .../test/test_sandbox_ue_controller_api.py | 47 + .../demo9/python/mecapp/test/test_scenario.py | 39 + .../mecapp/test/test_scenario_config.py | 39 + .../python/mecapp/test/test_service_config.py | 39 + .../python/mecapp/test/test_service_port.py | 39 + examples/demo9/python/mecapp/test/test_ue.py | 39 + .../demo9/python/mecapp/test/test_zone.py | 39 + examples/demo9/python/mecapp/tox.ini | 10 + .../notebook/MEC_And_oneM2M_Tutorial.ipynb | 3765 +++++++++++++++++ .../notebook/images/V2X Predicted QoS.jpg | Bin 0 -> 513891 bytes .../demo9/python/notebook/images/capif.png | Bin 0 -> 54534 bytes .../python/notebook/images/project_arch.jpg | Bin 0 -> 33056 bytes 257 files changed, 27838 insertions(+) create mode 100644 examples/demo9/README.md create mode 100644 examples/demo9/golang/Dockerfile create mode 100644 examples/demo9/golang/README.md create mode 100644 examples/demo9/golang/app_instance.yaml create mode 100755 examples/demo9/golang/build-demo9.sh create mode 100644 examples/demo9/golang/build_test.sh create mode 100644 examples/demo9/golang/client/README.md create mode 100644 examples/demo9/golang/client/api/swagger.yaml create mode 100644 examples/demo9/golang/client/api_authorization.go create mode 100644 examples/demo9/golang/client/api_sandbox_app_instances.go create mode 100644 examples/demo9/golang/client/api_sandbox_logs_subscriptions.go create mode 100644 examples/demo9/golang/client/api_sandbox_mec_services.go create mode 100644 examples/demo9/golang/client/api_sandbox_network_scenarios.go create mode 100644 examples/demo9/golang/client/api_sandbox_ue_controller.go create mode 100644 examples/demo9/golang/client/client.go create mode 100644 examples/demo9/golang/client/configuration.go create mode 100644 examples/demo9/golang/client/docs/ApplicationInfo.md create mode 100644 examples/demo9/golang/client/docs/AuthorizationApi.md create mode 100644 examples/demo9/golang/client/docs/CellularDomainConfig.md create mode 100644 examples/demo9/golang/client/docs/CellularPoaConfig.md create mode 100644 examples/demo9/golang/client/docs/ConnectivityConfig.md create mode 100644 examples/demo9/golang/client/docs/CpuConfig.md create mode 100644 examples/demo9/golang/client/docs/D2dConfig.md create mode 100644 examples/demo9/golang/client/docs/Deployment.md create mode 100644 examples/demo9/golang/client/docs/DnConfig.md create mode 100644 examples/demo9/golang/client/docs/Domain.md create mode 100644 examples/demo9/golang/client/docs/EgressService.md create mode 100644 examples/demo9/golang/client/docs/ExternalConfig.md create mode 100644 examples/demo9/golang/client/docs/GeoData.md create mode 100644 examples/demo9/golang/client/docs/GpuConfig.md create mode 100644 examples/demo9/golang/client/docs/IngressService.md create mode 100644 examples/demo9/golang/client/docs/LineString.md create mode 100644 examples/demo9/golang/client/docs/MemoryConfig.md create mode 100644 examples/demo9/golang/client/docs/NetworkCharacteristics.md create mode 100644 examples/demo9/golang/client/docs/NetworkLocation.md create mode 100644 examples/demo9/golang/client/docs/PhysicalLocation.md create mode 100644 examples/demo9/golang/client/docs/Poa4GConfig.md create mode 100644 examples/demo9/golang/client/docs/Poa5GConfig.md create mode 100644 examples/demo9/golang/client/docs/PoaWifiConfig.md create mode 100644 examples/demo9/golang/client/docs/Point.md create mode 100644 examples/demo9/golang/client/docs/ProblemDetails.md create mode 100644 examples/demo9/golang/client/docs/Process.md create mode 100644 examples/demo9/golang/client/docs/Sandbox.md create mode 100644 examples/demo9/golang/client/docs/SandboxAppInstances.md create mode 100644 examples/demo9/golang/client/docs/SandboxAppInstancesApi.md create mode 100644 examples/demo9/golang/client/docs/SandboxLogsSubscriptions.md create mode 100644 examples/demo9/golang/client/docs/SandboxLogsSubscriptionsApi.md create mode 100644 examples/demo9/golang/client/docs/SandboxMECServicesApi.md create mode 100644 examples/demo9/golang/client/docs/SandboxMecServices.md create mode 100644 examples/demo9/golang/client/docs/SandboxNetworkScenario.md create mode 100644 examples/demo9/golang/client/docs/SandboxNetworkScenariosApi.md create mode 100644 examples/demo9/golang/client/docs/SandboxUEControllerApi.md create mode 100644 examples/demo9/golang/client/docs/Scenario.md create mode 100644 examples/demo9/golang/client/docs/ScenarioConfig.md create mode 100644 examples/demo9/golang/client/docs/ServiceConfig.md create mode 100644 examples/demo9/golang/client/docs/ServicePort.md create mode 100644 examples/demo9/golang/client/docs/Ue.md create mode 100644 examples/demo9/golang/client/docs/Zone.md create mode 100644 examples/demo9/golang/client/git_push.sh create mode 100644 examples/demo9/golang/client/model_application_info.go create mode 100644 examples/demo9/golang/client/model_cellular_domain_config.go create mode 100644 examples/demo9/golang/client/model_cellular_poa_config.go create mode 100644 examples/demo9/golang/client/model_connectivity_config.go create mode 100644 examples/demo9/golang/client/model_cpu_config.go create mode 100644 examples/demo9/golang/client/model_d2d_config.go create mode 100644 examples/demo9/golang/client/model_deployment.go create mode 100644 examples/demo9/golang/client/model_dn_config.go create mode 100644 examples/demo9/golang/client/model_domain.go create mode 100644 examples/demo9/golang/client/model_egress_service.go create mode 100644 examples/demo9/golang/client/model_external_config.go create mode 100644 examples/demo9/golang/client/model_geo_data.go create mode 100644 examples/demo9/golang/client/model_gpu_config.go create mode 100644 examples/demo9/golang/client/model_ingress_service.go create mode 100644 examples/demo9/golang/client/model_line_string.go create mode 100644 examples/demo9/golang/client/model_memory_config.go create mode 100644 examples/demo9/golang/client/model_namespace.go create mode 100644 examples/demo9/golang/client/model_network_characteristics.go create mode 100644 examples/demo9/golang/client/model_network_location.go create mode 100644 examples/demo9/golang/client/model_oauth.go create mode 100644 examples/demo9/golang/client/model_physical_location.go create mode 100644 examples/demo9/golang/client/model_poa4_g_config.go create mode 100644 examples/demo9/golang/client/model_poa5_g_config.go create mode 100644 examples/demo9/golang/client/model_poa_wifi_config.go create mode 100644 examples/demo9/golang/client/model_point.go create mode 100644 examples/demo9/golang/client/model_problem_details.go create mode 100644 examples/demo9/golang/client/model_process.go create mode 100644 examples/demo9/golang/client/model_sandbox_app_instances.go create mode 100644 examples/demo9/golang/client/model_sandbox_logs_subscriptions.go create mode 100644 examples/demo9/golang/client/model_sandbox_mec_services.go create mode 100644 examples/demo9/golang/client/model_sandbox_network_scenario.go create mode 100644 examples/demo9/golang/client/model_scenario.go create mode 100644 examples/demo9/golang/client/model_scenario_config.go create mode 100644 examples/demo9/golang/client/model_service_config.go create mode 100644 examples/demo9/golang/client/model_service_port.go create mode 100644 examples/demo9/golang/client/model_ue.go create mode 100644 examples/demo9/golang/client/model_zone.go create mode 100644 examples/demo9/golang/client/response.go create mode 100755 examples/demo9/golang/docker_build.sh create mode 100755 examples/demo9/golang/docker_run.sh create mode 100755 examples/demo9/golang/dockerize.sh create mode 100755 examples/demo9/golang/entrypoint.sh create mode 100644 examples/demo9/golang/git_push.sh create mode 100644 examples/demo9/golang/go.mod create mode 100644 examples/demo9/golang/go.sum create mode 100644 examples/demo9/golang/main.go create mode 100644 examples/demo9/golang/routers.go create mode 100755 examples/demo9/golang/run.sh create mode 100644 examples/demo9/python/README.md create mode 100644 examples/demo9/python/mecapp/.gitignore create mode 100644 examples/demo9/python/mecapp/.swagger-codegen-ignore create mode 100644 examples/demo9/python/mecapp/.swagger-codegen/VERSION create mode 100644 examples/demo9/python/mecapp/.travis.yml create mode 100644 examples/demo9/python/mecapp/README.md create mode 100644 examples/demo9/python/mecapp/docs/ApplicationInfo.md create mode 100644 examples/demo9/python/mecapp/docs/AuthorizationApi.md create mode 100644 examples/demo9/python/mecapp/docs/CellularDomainConfig.md create mode 100644 examples/demo9/python/mecapp/docs/CellularPoaConfig.md create mode 100644 examples/demo9/python/mecapp/docs/ConnectivityConfig.md create mode 100644 examples/demo9/python/mecapp/docs/CpuConfig.md create mode 100644 examples/demo9/python/mecapp/docs/D2dConfig.md create mode 100644 examples/demo9/python/mecapp/docs/DNConfig.md create mode 100644 examples/demo9/python/mecapp/docs/Deployment.md create mode 100644 examples/demo9/python/mecapp/docs/Domain.md create mode 100644 examples/demo9/python/mecapp/docs/EgressService.md create mode 100644 examples/demo9/python/mecapp/docs/ExternalConfig.md create mode 100644 examples/demo9/python/mecapp/docs/GeoData.md create mode 100644 examples/demo9/python/mecapp/docs/GpuConfig.md create mode 100644 examples/demo9/python/mecapp/docs/IngressService.md create mode 100644 examples/demo9/python/mecapp/docs/LineString.md create mode 100644 examples/demo9/python/mecapp/docs/MemoryConfig.md create mode 100644 examples/demo9/python/mecapp/docs/NetworkCharacteristics.md create mode 100644 examples/demo9/python/mecapp/docs/NetworkLocation.md create mode 100644 examples/demo9/python/mecapp/docs/PhysicalLocation.md create mode 100644 examples/demo9/python/mecapp/docs/Poa4GConfig.md create mode 100644 examples/demo9/python/mecapp/docs/Poa5GConfig.md create mode 100644 examples/demo9/python/mecapp/docs/PoaWifiConfig.md create mode 100644 examples/demo9/python/mecapp/docs/Point.md create mode 100644 examples/demo9/python/mecapp/docs/ProblemDetails.md create mode 100644 examples/demo9/python/mecapp/docs/Process.md create mode 100644 examples/demo9/python/mecapp/docs/Sandbox.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxAppInstances.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxAppInstancesApi.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxLogsSubscriptions.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxLogsSubscriptionsApi.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxMECServicesApi.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxMecServices.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxNetworkScenario.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxNetworkScenariosApi.md create mode 100644 examples/demo9/python/mecapp/docs/SandboxUEControllerApi.md create mode 100644 examples/demo9/python/mecapp/docs/Scenario.md create mode 100644 examples/demo9/python/mecapp/docs/ScenarioConfig.md create mode 100644 examples/demo9/python/mecapp/docs/ServiceConfig.md create mode 100644 examples/demo9/python/mecapp/docs/ServicePort.md create mode 100644 examples/demo9/python/mecapp/docs/UE.md create mode 100644 examples/demo9/python/mecapp/docs/Zone.md create mode 100644 examples/demo9/python/mecapp/git_push.sh create mode 100644 examples/demo9/python/mecapp/requirements.txt create mode 100644 examples/demo9/python/mecapp/setup.py create mode 100644 examples/demo9/python/mecapp/swagger_client/__init__.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/__init__.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/authorization_api.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/sandbox_app_instances_api.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/sandbox_logs_subscriptions_api.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/sandbox_mec_services_api.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/sandbox_network_scenarios_api.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api/sandbox_ue_controller_api.py create mode 100644 examples/demo9/python/mecapp/swagger_client/api_client.py create mode 100644 examples/demo9/python/mecapp/swagger_client/configuration.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/__init__.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/application_info.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/cellular_domain_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/cellular_poa_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/connectivity_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/cpu_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/d2d_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/deployment.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/dn_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/domain.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/egress_service.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/external_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/geo_data.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/gpu_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/ingress_service.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/line_string.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/memory_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/namespace.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/network_characteristics.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/network_location.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/oauth.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/physical_location.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/poa4_g_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/poa5_g_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/poa_wifi_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/point.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/problem_details.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/process.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/sandbox.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/sandbox_app_instances.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/sandbox_logs_subscriptions.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/sandbox_mec_services.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/sandbox_network_scenario.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/scenario.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/scenario_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/service_config.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/service_port.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/ue.py create mode 100644 examples/demo9/python/mecapp/swagger_client/models/zone.py create mode 100644 examples/demo9/python/mecapp/swagger_client/rest.py create mode 100644 examples/demo9/python/mecapp/test-requirements.txt create mode 100644 examples/demo9/python/mecapp/test/__init__.py create mode 100644 examples/demo9/python/mecapp/test/test_application_info.py create mode 100644 examples/demo9/python/mecapp/test/test_authorization_api.py create mode 100644 examples/demo9/python/mecapp/test/test_cellular_domain_config.py create mode 100644 examples/demo9/python/mecapp/test/test_cellular_poa_config.py create mode 100644 examples/demo9/python/mecapp/test/test_connectivity_config.py create mode 100644 examples/demo9/python/mecapp/test/test_cpu_config.py create mode 100644 examples/demo9/python/mecapp/test/test_d2d_config.py create mode 100644 examples/demo9/python/mecapp/test/test_deployment.py create mode 100644 examples/demo9/python/mecapp/test/test_dn_config.py create mode 100644 examples/demo9/python/mecapp/test/test_domain.py create mode 100644 examples/demo9/python/mecapp/test/test_egress_service.py create mode 100644 examples/demo9/python/mecapp/test/test_external_config.py create mode 100644 examples/demo9/python/mecapp/test/test_geo_data.py create mode 100644 examples/demo9/python/mecapp/test/test_gpu_config.py create mode 100644 examples/demo9/python/mecapp/test/test_ingress_service.py create mode 100644 examples/demo9/python/mecapp/test/test_line_string.py create mode 100644 examples/demo9/python/mecapp/test/test_memory_config.py create mode 100644 examples/demo9/python/mecapp/test/test_network_characteristics.py create mode 100644 examples/demo9/python/mecapp/test/test_network_location.py create mode 100644 examples/demo9/python/mecapp/test/test_physical_location.py create mode 100644 examples/demo9/python/mecapp/test/test_poa4_g_config.py create mode 100644 examples/demo9/python/mecapp/test/test_poa5_g_config.py create mode 100644 examples/demo9/python/mecapp/test/test_poa_wifi_config.py create mode 100644 examples/demo9/python/mecapp/test/test_point.py create mode 100644 examples/demo9/python/mecapp/test/test_problem_details.py create mode 100644 examples/demo9/python/mecapp/test/test_process.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_app_instances.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_app_instances_api.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions_api.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_mec_services.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_mec_services_api.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_network_scenario.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_network_scenarios_api.py create mode 100644 examples/demo9/python/mecapp/test/test_sandbox_ue_controller_api.py create mode 100644 examples/demo9/python/mecapp/test/test_scenario.py create mode 100644 examples/demo9/python/mecapp/test/test_scenario_config.py create mode 100644 examples/demo9/python/mecapp/test/test_service_config.py create mode 100644 examples/demo9/python/mecapp/test/test_service_port.py create mode 100644 examples/demo9/python/mecapp/test/test_ue.py create mode 100644 examples/demo9/python/mecapp/test/test_zone.py create mode 100644 examples/demo9/python/mecapp/tox.ini create mode 100644 examples/demo9/python/notebook/MEC_And_oneM2M_Tutorial.ipynb create mode 100644 examples/demo9/python/notebook/images/V2X Predicted QoS.jpg create mode 100644 examples/demo9/python/notebook/images/capif.png create mode 100644 examples/demo9/python/notebook/images/project_arch.jpg diff --git a/examples/demo9/README.md b/examples/demo9/README.md new file mode 100644 index 000000000..6ed6929f2 --- /dev/null +++ b/examples/demo9/README.md @@ -0,0 +1 @@ +The main objective of this tutorial is to demonstrate how to use the MEC and oneM2M platforms jointly. diff --git a/examples/demo9/golang/Dockerfile b/examples/demo9/golang/Dockerfile new file mode 100644 index 000000000..decea7cee --- /dev/null +++ b/examples/demo9/golang/Dockerfile @@ -0,0 +1,26 @@ +# 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. + +FROM golang + + +# Some ENV variables +ENV SERVICE_NAME = "demo9" + +COPY ./demo9 /demo9 +COPY entrypoint.sh / + +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/examples/demo9/golang/README.md b/examples/demo9/golang/README.md new file mode 100644 index 000000000..418627898 --- /dev/null +++ b/examples/demo9/golang/README.md @@ -0,0 +1,145 @@ +Demo9 is a MEC application to illustrate the usage of the MEC Sandbox command line APIs. + +# How to use it + +## Building the demo9 application + +go version 1.18+ is required to build demo 6 + +There is two ways to build demo9 application: +- Using the docker_build.sh script + +```sh +~$ docker pull golang +~$ cd ~/AdvantEDGE/examples/demo9 +~/AdvantEDGE/examples/demo9$ docker_build.sh +``` + +- Manually: + +```sh +~$ docker pull golang +~$ cd ~/AdvantEDGE/examples/demo9 +~/AdvantEDGE/examples/demo9$ docker run --rm -it -v$PWD:/opt/local/etsi/demo9 golang +root@56c7b1ce74ca:/go# cd /opt/local/etsi/demo9 +root@56c7b1ce74ca:/opt/local/etsi/demo9# go run ./main.go +``` + +## Executing the demo9 application + +The demo9 application can be executed using the script run.sh: + +```sh +~$ cd ~/AdvantEDGE/examples/demo9 +~/AdvantEDGE/examples/demo9$ docker_run.sh +``` + +# Menu description + +Below is the menu proposed by the demo9 application: + +```sh +Mandatory commands: + l: Login, n: Get Namespace, L: Logout, s: Get scenarios list + a : Activate a scenario, A: Terminate a scenario +Optional commands: + S : Get scenario description + m: Get MEC application services list + i: Get application instances list, c: Create a new application instance, C: Delete a new application instance + u: Get UEs, x : Increase UE, X : Decrease UE + T: Current status: +MEC 011 App Support: + y: Send ConfirmReady, r: Send Registration, R: Send Deregistration +MEC 011 Service Management: + v: Create new service, V: Delete service, g: Get list of MEC services +MEC 030: + Y: Get V2X UU unicast setting', z: V2X Msg subscription, Z : Delete V2X subscription, Q <[latutudes] [longitudes] [timestamps]: Provide PredictedQoS + [latitudes] is a set of latitudes separated by comma, [longitudes] is a set of longitudes separated by comma, [timestamps] + E.g. 43.729416,43.732456 7.414853,7.418417 1653295620,1653299220 +MEC 040: + 0: Get Federation Systems list', 1 : Get Federation Services list, 2 : Get Federation Service, 3: Subscribe, 4 []: Get subscription, 5 : Delete subscription +q: Quit +Enter your choice: +``` + +## Mandatories commands + +Mandatories commands are the sequence of command to execute before to execute with the optionals commands. + +### Login command + +The Login command (l) authenticates and authorizes the MEC application demo9 and creates a new MEC sandbox instance. + +### Logout command + +The Logout command (L) terminates an existing MEC sandbox instance. + +### Get scenarios list + +After the login step, it is mandatory to request the list of available network scenarios in order to execute with the optional commands. + +## Optional commands + +### Get scenario description + +This option (S) uses the index of the network scenario (starting from 0 i.e. S 0) to retrieve the description of the selected network scenario. + +### Activate a network scenario + +This option (a) uses the index of the network scenario (starting from 0 i.e. a 0) to activate the selected network scenario. This command requests the MEC Sandbox instance to start all the MEC services attached to the activated network scenario. + +### Deactivate a network scenario + +This option (d) uses the index of the network scenario (starting from 0 i.e. d 0) to deactivate the selected network scenario. This command requests the MEC Sandbox instance to terminate all the MEC services attached to the activated network scenario. + +### Get MEC services list + +This option (m) retrieves the list of the MEC services available with the activated network scenario. + +### Get application instances list + +This option (i) retrieves the list of the MEC applications available with the activated network scenario. + +### Create a new application instance + +This option (c) creates the a new USER MEC application. The application instance id is generated automatically and its name is "demo9". +This new application is attached to "mep1". + +Note: Additional new application instances can be created to simulate several MEC application. This demo application is limited to one new USER MEC application. + +### Delete a new application instance + +This option (C) terminates an existing MEC application. + +## MEC Services commands + +Theses commands provides some example of access to the MEC services available with the activated network scenario. + +### MEC Application Support (MEC 011 service) + +- The option (y) sends a confirm-ready to the MEC platform to indicate a READY state. +- The option (r) registers the MEC application to the MEC platform (optional). +- The option (R) de-registers the MEC application from the MEC platform (optional). + +### MEC Service Managenment (MEC 011 service) + + +### Get V2X UU unicast setting (MEC 030 service) + +- The option (Y) retrieves the UU Unicast settings from the MEC 030 service. To use it, the V2X network scenario shall be activated (see [Activate a network scenario](#activate_a_network_scenario)). +- The option (z) creates a subscription on V2X messages. +- The option (Z) deletes a subscription. + +## Application status + +The option (Q) provides the demo9 application status. If a Login commands was executed, the termination process does the logout. + +``` +Current status: Sandbox: sbxqvgq4q4, appsInfo.Id: d75d8536-cf94-45a6-91a3-fc5b033f9630, Subscription: sub-wwJ_uzHOwqPntaia, Demo9 app not registered +``` + +In the example above, the MEC Platform identifier is sbxqvgq4q4, the MEC application identifier is d75d8536-cf94-45a6-91a3-fc5b033f9630 and a subscription to the applicationTerminationNotifcation was created: sub-wwJ_uzHOwqPntaia. Note that the MEC application is not registered to the MEC Platform. + +## Terminate the demo9 application + +The command Quit (q) terminates the demo9 application. If a Login commands was executed, the termination process does the logout, deletes all subscriptions, de-registers the MEC appliction if a register was done and terminates an existing MEC sandbox instance. diff --git a/examples/demo9/golang/app_instance.yaml b/examples/demo9/golang/app_instance.yaml new file mode 100644 index 000000000..8951ab160 --- /dev/null +++ b/examples/demo9/golang/app_instance.yaml @@ -0,0 +1,18 @@ +# This file defines the configuration of demo9 edge application. All fields are required to run demo-6 on MEC Sandbox + +# Set where mec application is running either on MEC Sandbox or AdvantEDGE. Expected fields: sandbox | advantedge +mode: 'sandbox' +# Set MEC plateform address +sandbox: 'https://mec-platform.etsi.org/.etsi.org' +# Set if sandbox url uses https. Expected fields: true | false +https: true +# Set the mec platform name demo-6 will run on. Example field: mep1 +mecplatform: 'mep1' +# Set host address of demo-6. +localurl: 'http://' +# Set host port number of demo-6. Example field: '8093' +port: '80' +# Callback base URL +callbackUrl: 'http://lab-oai.etsi.org' +# Callback port for listener +callbackPort: '80' diff --git a/examples/demo9/golang/build-demo9.sh b/examples/demo9/golang/build-demo9.sh new file mode 100755 index 000000000..9185efe63 --- /dev/null +++ b/examples/demo9/golang/build-demo9.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e +set -x + +# Get full path to script directory +SCRIPT=$(readlink -f "$0") +BASEDIR=$(dirname "$SCRIPT") + +DEMOBIN=$BASEDIR/bin/demo6 + +echo "" +echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +echo ">>> Building Demo 9 Go MEC APP" +echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +echo "" + +go mod tidy +go build -o $DEMOBIN . + +echo "" +echo ">>> Demo Service build completed" diff --git a/examples/demo9/golang/build_test.sh b/examples/demo9/golang/build_test.sh new file mode 100644 index 000000000..da9c7eaff --- /dev/null +++ b/examples/demo9/golang/build_test.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e +set -x + +# Get full path to script directory +SCRIPT=$(readlink -f "$0") +BASEDIR=$(dirname "$SCRIPT") + +DEMOBIN=$BASEDIR/bin/demo9 + +docker pull golang +docker run --rm -it -v$PWD:/opt/local/etsi/demo9 golang bash -c "cd /opt/local/etsi/demo9 && ./build-demo9.sh" + +echo "" +echo ">>> Demo Service build completed" diff --git a/examples/demo9/golang/client/README.md b/examples/demo9/golang/client/README.md new file mode 100644 index 000000000..5f189fd74 --- /dev/null +++ b/examples/demo9/golang/client/README.md @@ -0,0 +1,84 @@ +# Go API client for swagger + +The MEC Sandbox API 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: 0.0.9 +- 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 *http://localhost/sandbox-api/v1* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*AuthorizationApi* | [**Login**](docs/AuthorizationApi.md#login) | **Post** /login | Initiate OAuth login procedure and creates a MEC Sandbox instance +*AuthorizationApi* | [**Logout**](docs/AuthorizationApi.md#logout) | **Post** /logout | Terminates User Session and delete the Sandbox instance +*SandboxAppInstancesApi* | [**SandboxAppInstancesDELETE**](docs/SandboxAppInstancesApi.md#sandboxappinstancesdelete) | **Delete** /sandboxAppInstances/{app_instance_id} | Delete an existing application instance +*SandboxAppInstancesApi* | [**SandboxAppInstancesGET**](docs/SandboxAppInstancesApi.md#sandboxappinstancesget) | **Get** /sandboxAppInstances | Get the list of the available application instance identifiers +*SandboxAppInstancesApi* | [**SandboxAppInstancesPOST**](docs/SandboxAppInstancesApi.md#sandboxappinstancespost) | **Post** /sandboxAppInstances | Create a new application instance identifier +*SandboxLogsSubscriptionsApi* | [**SandboxLogsSubscriptionsDELETE**](docs/SandboxLogsSubscriptionsApi.md#sandboxlogssubscriptionsdelete) | **Delete** /sandboxLogsSubscriptions/{subscription_reference} | Subscription to receive logs from the sandbox +*SandboxLogsSubscriptionsApi* | [**SandboxLogsSubscriptionsPOST**](docs/SandboxLogsSubscriptionsApi.md#sandboxlogssubscriptionspost) | **Post** /sandboxLogsSubscriptions | Subscription to receive logs from the sandbox +*SandboxMECServicesApi* | [**SandboxMecServicesGET**](docs/SandboxMECServicesApi.md#sandboxmecservicesget) | **Get** /sandboxMecServices | Get the list of the available MEC services +*SandboxNetworkScenariosApi* | [**SandboxIndividualNetworkScenariosGET**](docs/SandboxNetworkScenariosApi.md#sandboxindividualnetworkscenariosget) | **Get** /sandboxNetworkScenarios/{network_scenario_id} | Get description of a Network Scenario to be used. +*SandboxNetworkScenariosApi* | [**SandboxNetworkScenarioDELETE**](docs/SandboxNetworkScenariosApi.md#sandboxnetworkscenariodelete) | **Delete** /sandboxNetworkScenarios/{network_scenario_id} | Deactivate the Network Scenario. +*SandboxNetworkScenariosApi* | [**SandboxNetworkScenarioPOST**](docs/SandboxNetworkScenariosApi.md#sandboxnetworkscenariopost) | **Post** /sandboxNetworkScenarios/{network_scenario_id} | Selects the Network Scenario to be used. +*SandboxNetworkScenariosApi* | [**SandboxNetworkScenariosGET**](docs/SandboxNetworkScenariosApi.md#sandboxnetworkscenariosget) | **Get** /sandboxNetworkScenarios | Get the list of the available network scenarios +*SandboxUEControllerApi* | [**SandboxUeControllerGET**](docs/SandboxUEControllerApi.md#sandboxuecontrollerget) | **Get** /sandboxUeController | Get the list of the available UEs (e.g. \"Stationary UE\") +*SandboxUEControllerApi* | [**SandboxUeControllerPATCH**](docs/SandboxUEControllerApi.md#sandboxuecontrollerpatch) | **Patch** /sandboxUeController/{user_equipment_id}/{user_equipment_value} | set the new value of the UE + +## Documentation For Models + + - [ApplicationInfo](docs/ApplicationInfo.md) + - [CellularDomainConfig](docs/CellularDomainConfig.md) + - [CellularPoaConfig](docs/CellularPoaConfig.md) + - [ConnectivityConfig](docs/ConnectivityConfig.md) + - [CpuConfig](docs/CpuConfig.md) + - [D2dConfig](docs/D2dConfig.md) + - [Deployment](docs/Deployment.md) + - [DnConfig](docs/DnConfig.md) + - [Domain](docs/Domain.md) + - [EgressService](docs/EgressService.md) + - [ExternalConfig](docs/ExternalConfig.md) + - [GeoData](docs/GeoData.md) + - [GpuConfig](docs/GpuConfig.md) + - [IngressService](docs/IngressService.md) + - [LineString](docs/LineString.md) + - [MemoryConfig](docs/MemoryConfig.md) + - [NetworkCharacteristics](docs/NetworkCharacteristics.md) + - [NetworkLocation](docs/NetworkLocation.md) + - [PhysicalLocation](docs/PhysicalLocation.md) + - [Poa4GConfig](docs/Poa4GConfig.md) + - [Poa5GConfig](docs/Poa5GConfig.md) + - [PoaWifiConfig](docs/PoaWifiConfig.md) + - [Point](docs/Point.md) + - [ProblemDetails](docs/ProblemDetails.md) + - [Process](docs/Process.md) + - [Sandbox](docs/Sandbox.md) + - [SandboxAppInstances](docs/SandboxAppInstances.md) + - [SandboxLogsSubscriptions](docs/SandboxLogsSubscriptions.md) + - [SandboxMecServices](docs/SandboxMecServices.md) + - [SandboxNetworkScenario](docs/SandboxNetworkScenario.md) + - [Scenario](docs/Scenario.md) + - [ScenarioConfig](docs/ScenarioConfig.md) + - [ServiceConfig](docs/ServiceConfig.md) + - [ServicePort](docs/ServicePort.md) + - [Ue](docs/Ue.md) + - [Zone](docs/Zone.md) + +## Documentation For Authorization + Endpoints do not require authorization. + + +## Author + +cti_support@etsi.org diff --git a/examples/demo9/golang/client/api/swagger.yaml b/examples/demo9/golang/client/api/swagger.yaml new file mode 100644 index 000000000..35426b79d --- /dev/null +++ b/examples/demo9/golang/client/api/swagger.yaml @@ -0,0 +1,1521 @@ +openapi: 3.0.0 +info: + title: MEC Sandbox API + description: The MEC Sandbox API described using OpenAPI + contact: + email: cti_support@etsi.org + license: + name: BSD-3-Clause + url: https://forge.etsi.org/legal-matters + version: 1.0.0 +servers: +- url: http://localhost/sandbox-api/v1 +paths: + /login: + post: + tags: + - Authorization + summary: Initiate OAuth login procedure and creates a MEC Sandbox instance + description: Initiate OAuth login procedure and creates a MEC Sandbox instance + operationId: login + parameters: + - name: provider + in: query + description: Oauth provider + required: true + style: form + explode: true + schema: + type: string + enum: + - GITHUB + responses: + "201": + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/Oauth' + "400": + description: Bad Request + content: {} + "401": + description: Unauthorized + content: {} + "404": + description: Not Found + content: {} + /namespace: + get: + tags: + - Authorization + summary: Get the namespace against the User Code + description: Get the namespace against the User Code + operationId: GetNamespace + parameters: + - name: user_code + in: query + description: User Code obtained from the login endpoint + required: true + style: form + explode: true + schema: + type: string + responses: + "200": + description: This status code indicates that the request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/Namespace' + "400": + description: Bad Request + content: {} + "401": + description: Unauthorized + content: {} + "404": + description: Not Found + content: {} + /logout: + post: + tags: + - Authorization + summary: Terminates User Session and delete the Sandbox instance + description: Terminates User Session and delete the Sandbox instance + operationId: logout + parameters: + - name: sandbox_name + in: query + description: Sandbox identifier + required: true + style: form + explode: true + schema: + type: string + responses: + "200": + description: OK + content: {} + "400": + description: Bad Request + content: {} + "401": + description: Unauthorized + content: {} + "404": + description: Not Found + content: {} + /sandboxNetworkScenarios: + get: + tags: + - Sandbox Network Scenarios + summary: Get the list of the available network scenarios + description: This method retrieves the list of the available network scenarios. + operationId: SandboxNetworkScenariosGET + parameters: + - name: sandbox_name + in: query + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + responses: + "200": + description: "Upon success, a response message content containing an array\ + \ of the list of the available network scenarios." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SandboxNetworkScenario' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No network scenario found." + /sandboxNetworkScenarios/{sandbox_name}: + get: + tags: + - Sandbox Network Scenarios + summary: Get description of a Network Scenario to be used. + description: This method retrive description of a the network scenario + operationId: SandboxIndividualNetworkScenariosGET + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + - name: network_scenario_id + in: query + description: Network scenario to retrieve + required: true + style: simple + explode: false + schema: + type: string + enum: + - 4g-5g-macro-v2x + - 4g-5g-macro-v2x-fed + - 4g-5g-wifi-macro + - 4g-macro + - 4g-wifi-macro + - dual-mep-4g-5g-wifi-macro + - dual-mep-short-path + x-exportParamName: Provider + x-optionalDataType: String + responses: + "200": + description: "Upon success, an empty response message." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Scenario' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : used when a client provided a URI that cannot\ + \ be mapped to a valid resource URI." + post: + tags: + - Sandbox Network Scenarios + summary: Selects the Network Scenario to be activated. + description: This method selects the network scenario to be activated. This + request initiates the creation of necessary MEC services for specific network + scenario + operationId: SandboxNetworkScenarioPOST + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + - name: network_scenario_id + in: query + description: Network scenario to be used + required: true + style: simple + explode: false + schema: + type: string + enum: + - 4g-5g-macro-v2x + - 4g-5g-macro-v2x-fed + - 4g-5g-wifi-macro + - 4g-macro + - 4g-wifi-macro + - dual-mep-4g-5g-wifi-macro + - dual-mep-short-path + x-exportParamName: Provider + x-optionalDataType: String + responses: + "201": + description: "Upon success, an empty response message." + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : used when a client provided a URI that cannot\ + \ be mapped to a valid resource URI." + /sandboxNetworkScenarios/{sandbox_name}/{network_scenario_id}: + delete: + tags: + - Sandbox Network Scenarios + summary: Deactivate the Network Scenario. + description: This method deactivates the network scenario + operationId: SandboxNetworkScenarioDELETE + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + - name: network_scenario_id + in: path + description: Network scenario to be used + required: true + style: simple + explode: false + schema: + type: string + enum: + - 4g-5g-macro-v2x + - 4g-5g-macro-v2x-fed + - 4g-5g-wifi-macro + - 4g-macro + - 4g-wifi-macro + - dual-mep-4g-5g-wifi-macro + - dual-mep-short-path + x-exportParamName: Provider + x-optionalDataType: String + responses: + "204": + description: "Upon success, an empty response message." + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : used when a client provided a URI that cannot\ + \ be mapped to a valid resource URI." + /apiConsoleLogs/{sandbox_name}: + get: + tags: + - API Console + summary: Get the list of http logs in the activated scenario. + description: Get the list of http logs in the activated scenario. + operationId: ApiConsoleLogsGET + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + responses: + "200": + description: "Upon success, a response message content containing an array of the list of the HTTP logs." + content: + application/json: + schema: + type: array + items: + type: object + description: Object representing the HTTP logs. + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No Activated Scenario found against the provided sandbox." + /sandboxUeController/{sandbox_name}: + get: + tags: + - Sandbox UE Controller + summary: Get the list of the available UEs (e.g. "Stationary UE") + description: This method retrieves the list of the available available UEs. + operationId: SandboxUeControllerGET + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + responses: + "200": + description: "Upon success, a response message content containing an array\ + \ of the list of the available UEs." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UE' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No UE found." + patch: + tags: + - Sandbox UE Controller + summary: set the new value of the UE + description: This method sets the new value of the UE. + operationId: SandboxUeControllerPATCH + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + - name: user_equipment_id + in: query + description: User equipmenet identifier + required: true + style: simple + explode: false + schema: + type: string + enum: + - Stationary_UE + - Low_Velocity_UE + - High_Velocity_UE + - name: user_equipment_value + in: query + description: It uniquely identifies a UE to set the new value + required: true + style: simple + explode: true + schema: + type: integer + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + responses: + "200": + description: "Upon success, an empty response message." + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No UE found." + /sandboxMecServices/{sandbox_name}: + get: + tags: + - Sandbox MEC Services + summary: Get the list of the available MEC services + description: This method retrieves the list of the available MEC services. + operationId: SandboxMecServicesGET + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + responses: + "200": + description: "Upon success, a response message content containing an array\ + \ of the list of the available MEC services." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SandboxMecServices' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No MEC services found." + /sandboxAppInstances/{sandbox_name}: + get: + tags: + - Sandbox App Instances + summary: Get the list of the available application instance identifiers + description: This method retrieves the list of the available application instance + identifiers + operationId: SandboxAppInstancesGET + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + responses: + "200": + description: "Upon success, a response message content containing an array\ + \ of the list of the available application instance identifier." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApplicationInfo' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No application instance identifier found." + post: + tags: + - Sandbox App Instances + summary: Create a new application instance identifier + description: This method creates a new application instance + operationId: SandboxAppInstancesPOST + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + requestBody: + description: Pet to add to the store + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationInfo' + required: true + responses: + "201": + description: "Upon success, a response message content containing an array\ + \ of the list of the available application instance identifier." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApplicationInfo' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No application instance identifier found." + /sandboxAppInstances/{sandbox_name}/{app_instance_id}: + delete: + tags: + - Sandbox App Instances + summary: Delete an existing application instance + description: This method removes an existing application instance + operationId: SandboxAppInstancesDELETE + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + - name: app_instance_id + in: path + description: It uniquely identifies a MEC application instance identifier + required: true + style: simple + explode: false + schema: + type: string + responses: + "204": + description: No content. + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : No application instance identifier found." + /sandboxLogsSubscriptions/{sandbox_name}: + post: + tags: + - Sandbox Logs Subscriptions + summary: Subscription to receive logs from the sandbox + description: This method is used to receive logs from the sandbox. + operationId: SandboxLogsSubscriptionsPOST + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + responses: + "201": + description: "Upon success, a response message content containing the subscription\ + \ reference." + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SandboxLogsSubscriptions' + x-content-type: application/json + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + /sandboxLogsSubscriptions/{sandbox_name}/{subscription_reference}: + delete: + tags: + - Sandbox Logs Subscriptions + summary: Subscription to receive logs from the sandbox + description: This method is used to receive logs from the sandbox. + operationId: SandboxLogsSubscriptionsDELETE + parameters: + - name: sandbox_name + in: path + description: Sandbox identifier + required: true + style: simple + explode: true + schema: + type: string + - name: subscription_reference + in: path + description: It uniquely identifies subscription reference to receive logs + from the sandbox + required: true + style: simple + explode: false + schema: + type: string + responses: + "204": + description: "Upon success, an empty response message." + "400": + description: "Bad Request : used to indicate that incorrect parameters were\ + \ passed to the request." + "401": + description: "Unauthorized : used when the client did not submit credentials." + "404": + description: "Not Found : Subscription reference not found." +components: + schemas: + SandboxNetworkScenario: + title: SandboxNetworkScenario + required: + - id + type: object + properties: + id: + type: string + description: The network scenario name. + example: "[\"4g-5g-macro\"]" + example: + id: "[\"4g-5g-macro\"]" + Scenario: + type: object + properties: + version: + type: string + description: Scenario version + id: + type: string + description: Unique scenario ID + name: + type: string + description: Unique scenario name + description: + type: string + description: User description of the scenario. + config: + $ref: '#/components/schemas/ScenarioConfig' + deployment: + $ref: '#/components/schemas/Deployment' + description: Scenario object + example: {} + ScenarioConfig: + type: object + properties: + visualization: + type: string + description: Visualization configuration + other: + type: string + description: Other scenario configuration + description: Scenario configuration + example: + visualization: visualization + other: other + Deployment: + type: object + properties: + netChar: + $ref: '#/components/schemas/NetworkCharacteristics' + connectivity: + $ref: '#/components/schemas/ConnectivityConfig' + d2d: + $ref: '#/components/schemas/D2dConfig' + interDomainLatency: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latency" + interDomainLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation" + interDomainThroughput: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl\ + \ and throughputDl" + interDomainPacketLoss: + type: number + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss" + format: double + meta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + userMeta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + domains: + type: array + items: + $ref: '#/components/schemas/Domain' + description: Network deployment object + example: {} + NetworkCharacteristics: + type: object + properties: + latency: + type: integer + description: Latency in ms + latencyVariation: + type: integer + description: Latency variation in ms + latencyDistribution: + type: string + description: "Latency distribution. Can only be set in the Scenario Deployment\ + \ network characteristics, ignored otherwise. Latency distribution is\ + \ set for the whole network and applied to every end-to-end traffic flows.\ + \ Default value is 'Normal' distribution." + enum: + - Normal + - Pareto + - Paretonormal + - Uniform + throughput: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by throughputUl\ + \ and throughputDl" + throughputDl: + type: integer + description: Downlink throughput limit in Mbps + throughputUl: + type: integer + description: Uplink throughput limit in Mbps + packetLoss: + type: number + description: Packet loss percentage + format: double + description: Network characteristics object + example: {} + ConnectivityConfig: + type: object + properties: + model: + type: string + description: "Connectivity Model:
  • OPEN: Any node in the scenario can\ + \ communicate with any node
  • PDU: Terminal nodes (UE) require a PDU\ + \ session to the target DN" + enum: + - OPEN + - PDU + example: {} + D2dConfig: + type: object + properties: + d2dMaxDistance: + type: number + description: Maximum distance for D2D. Default distance is 100m + disableD2dViaNetwork: + type: boolean + description: Enable-Disable D2D via network. Default value is false + description: D2D config + Domain: + type: object + properties: + id: + type: string + description: Unique domain ID + name: + type: string + description: Domain name + type: + type: string + description: Domain type + enum: + - OPERATOR + - OPERATOR-CELLULAR + - PUBLIC + netChar: + $ref: '#/components/schemas/NetworkCharacteristics' + interZoneLatency: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latency" + interZoneLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation" + interZoneThroughput: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl\ + \ and throughputDl" + interZonePacketLoss: + type: number + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss" + format: double + meta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + userMeta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + cellularDomainConfig: + $ref: '#/components/schemas/CellularDomainConfig' + zones: + type: array + items: + $ref: '#/components/schemas/Zone' + description: Operator domain object + example: {} + CellularDomainConfig: + type: object + properties: + mnc: + type: string + description: Mobile Network Code part of PLMN identity as defined in ETSI + TS 136 413 + mcc: + type: string + description: Mobile Country Code part of PLMN identity as defined in ETSI + TS 136 413 + defaultCellId: + type: string + description: The E-UTRAN Cell Identity as defined in ETSI TS 136 413 if + no cellId is defined for the cell or if not applicable + description: Cellular domain configuration information + example: {} + Zone: + type: object + properties: + id: + type: string + description: Unique zone ID + name: + type: string + description: Zone name + type: + type: string + description: Zone type + enum: + - ZONE + - COMMON + netChar: + $ref: '#/components/schemas/NetworkCharacteristics' + interFogLatency: + type: integer + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + interFogLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + interFogThroughput: + type: integer + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + interFogPacketLoss: + type: number + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + format: double + interEdgeLatency: + type: integer + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + interEdgeLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + interEdgeThroughput: + type: integer + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + interEdgePacketLoss: + type: number + description: "**DEPRECATED** As of release 1.3.0, no longer supported" + format: double + edgeFogLatency: + type: integer + description: "**DEPRECATED** As of release 1.3.0, replaced by netChar latency" + edgeFogLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.3.0, replaced by netChar latencyVariation" + edgeFogThroughput: + type: integer + description: "**DEPRECATED** As of release 1.3.0, replaced by netChar throughput" + edgeFogPacketLoss: + type: number + description: "**DEPRECATED** As of release 1.3.0, replaced by netChar packetLoss" + format: double + meta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + userMeta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + networkLocations: + type: array + items: + $ref: '#/components/schemas/NetworkLocation' + description: Logical zone (MEC network) object + example: {} + NetworkLocation: + type: object + properties: + id: + type: string + description: Unique network location ID + name: + type: string + description: Network location name + type: + type: string + description: Network location type + enum: + - POA + - POA-4G + - POA-5G + - POA-WIFI + - DEFAULT + netChar: + $ref: '#/components/schemas/NetworkCharacteristics' + terminalLinkLatency: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latency" + terminalLinkLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation" + terminalLinkThroughput: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl\ + \ and throughputDl" + terminalLinkPacketLoss: + type: number + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss" + format: double + meta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + userMeta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + cellularPoaConfig: + $ref: '#/components/schemas/CellularPoaConfig' + poa4GConfig: + $ref: '#/components/schemas/Poa4GConfig' + poa5GConfig: + $ref: '#/components/schemas/Poa5GConfig' + poaWifiConfig: + $ref: '#/components/schemas/PoaWifiConfig' + geoData: + $ref: '#/components/schemas/GeoData' + physicalLocations: + type: array + items: + $ref: '#/components/schemas/PhysicalLocation' + description: Logical network location object + example: {} + CellularPoaConfig: + type: object + properties: + cellId: + type: string + description: The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including + the ID of the eNB serving the cell + description: "**DEPRECATED** As of release 1.5.1, renamed to poa4GConfig" + Poa4GConfig: + type: object + properties: + cellId: + type: string + description: The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including + the ID of the eNB serving the cell + description: Cellular 4G POA configuration information + Poa5GConfig: + type: object + properties: + cellId: + type: string + description: The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including + the ID of the NR serving the cell + description: Cellular 5G POA configuration information + PoaWifiConfig: + type: object + properties: + macId: + type: string + description: WIFI POA MAC Address + description: WIFI POA configuration information + GeoData: + type: object + properties: + location: + $ref: '#/components/schemas/Point' + radius: + type: number + description: Optional - Radius (in meters) around the location + path: + $ref: '#/components/schemas/LineString' + eopMode: + type: string + description: "End-of-Path mode:
  • LOOP: When path endpoint is reached,\ + \ start over from the beginning
  • REVERSE: When path endpoint is reached,\ + \ return on the reverse path" + enum: + - LOOP + - REVERSE + velocity: + type: number + description: Speed of movement along path in m/s + d2dInRange: + type: array + items: + type: string + description: D2D UEs visible to UE + poaInRange: + type: array + items: + type: string + description: POAs visible to UE + description: Geographic data + Point: + required: + - type + type: object + properties: + type: + type: string + description: Must be Point + enum: + - Point + coordinates: + type: array + description: "For a Point, coordinates MUST be an array of two decimal numbers;\ + \ longitude and latitude precisely in that order" + items: + type: number + description: A single position in coordinate space (GeoJSON); a position is + an array of two numbers + externalDocs: + url: https://tools.ietf.org/html/rfc7946 + LineString: + required: + - type + type: object + properties: + type: + type: string + description: Must be LineString + enum: + - LineString + coordinates: + type: array + description: "For a LineString, coordinates is an array of two or more positions;\ + \ a position is an array of two decimal numbers (longitude and latitude\ + \ precisely in that order)" + items: + type: array + items: + type: number + description: An array of two or more positions in coordinate space (GeoJSON); + a position is an array of two numbers + externalDocs: + url: https://tools.ietf.org/html/rfc7946 + PhysicalLocation: + type: object + properties: + id: + type: string + description: Unique physical location ID + name: + type: string + description: Physical location name + type: + type: string + description: Physical location type + enum: + - UE + - FOG + - EDGE + - CN + - DC + isExternal: + type: boolean + description: |- + true: Physical location is external to MEEP + false: Physical location is internal to MEEP + geoData: + $ref: '#/components/schemas/GeoData' + networkLocationsInRange: + type: array + items: + type: string + description: Names of network locations within range of physical location + connected: + type: boolean + description: |- + true: Physical location has network connectivity + false: Physical location has no network connectivity + wireless: + type: boolean + description: |- + true: Physical location uses a wireless connection + false: Physical location uses a wired connection + wirelessType: + type: string + description: |- + Prioritized, comma-separated list of supported wireless connection types. + Default priority if not specififed is 'wifi,5g,4g,other'. + Wireless connection types: + - 4g + - 5g + - wifi + - other + dataNetwork: + $ref: '#/components/schemas/DNConfig' + meta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + userMeta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + processes: + type: array + items: + $ref: '#/components/schemas/Process' + netChar: + $ref: '#/components/schemas/NetworkCharacteristics' + linkLatency: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latency" + linkLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation" + linkThroughput: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl\ + \ and throughputDl" + linkPacketLoss: + type: number + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss" + format: double + macId: + type: string + description: Physical location MAC Address + description: Physical location object + example: {} + DNConfig: + type: object + properties: + dnn: + type: string + description: Data Network Name + ladn: + type: boolean + description: |- + true: Data network serves local area only + false: Data network is not limited to local area + ecsp: + type: string + description: Edge Compute Service Provider + description: Data Network Configuration + example: {} + Process: + type: object + properties: + id: + type: string + description: Unique process ID + name: + type: string + description: Process name + type: + type: string + description: Process type + enum: + - UE-APP + - EDGE-APP + - MEC-SVC + - CLOUD-APP + isExternal: + type: boolean + description: |- + true: process is external to MEEP + false: process is internal to MEEP + image: + type: string + description: Docker image to deploy inside MEEP + environment: + type: string + description: "Environment variables using the format NAME=\"value\",NAME=\"\ + value\",NAME=\"value\"" + commandArguments: + type: string + description: Arguments to command executable + commandExe: + type: string + description: Executable to invoke at container start up + serviceConfig: + $ref: '#/components/schemas/ServiceConfig' + gpuConfig: + $ref: '#/components/schemas/GpuConfig' + memoryConfig: + $ref: '#/components/schemas/MemoryConfig' + cpuConfig: + $ref: '#/components/schemas/CpuConfig' + externalConfig: + $ref: '#/components/schemas/ExternalConfig' + status: + type: string + description: Process status + userChartLocation: + type: string + description: Chart location for the deployment of the chart provided by + the user + userChartAlternateValues: + type: string + description: Chart values.yaml file location for the deployment of the chart + provided by the user + userChartGroup: + type: string + description: Chart supplemental information related to the group (service) + meta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + userMeta: + type: object + additionalProperties: + type: string + description: "Key/Value Pair Map (string, string)" + netChar: + $ref: '#/components/schemas/NetworkCharacteristics' + appLatency: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latency" + appLatencyVariation: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation" + appThroughput: + type: integer + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl\ + \ and throughputDl" + appPacketLoss: + type: number + description: "**DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss" + format: double + placementId: + type: string + description: Identifier used for process placement in AdvantEDGE cluster + description: Application or service object + example: {} + ServiceConfig: + type: object + properties: + name: + type: string + description: Unique service name + meSvcName: + type: string + description: "Multi-Edge service name, if any" + ports: + type: array + items: + $ref: '#/components/schemas/ServicePort' + description: Service object + example: {} + ServicePort: + type: object + properties: + protocol: + type: string + description: Protocol that the application is using (TCP or UDP) + port: + type: integer + description: Port number that the service is listening on + externalPort: + type: integer + description: | + External port number on which to expose the application (30000 - 32767)
  • Only one application allowed per external port
  • Scenario builder must configure to prevent conflicts + description: Service port object + example: {} + GpuConfig: + type: object + properties: + type: + type: string + description: Requested GPU type + count: + type: integer + description: Number of GPUs requested + description: GPU configuration object + MemoryConfig: + type: object + properties: + min: + type: integer + description: Minimum requested memory + max: + type: integer + description: Maximum requested memory + description: Memory configuration object + CpuConfig: + type: object + properties: + min: + type: number + description: Minimum requested CPU + format: float + max: + type: number + description: Maximum requested CPU + format: float + description: CPU configuration object + ExternalConfig: + type: object + properties: + ingressServiceMap: + type: array + items: + $ref: '#/components/schemas/IngressService' + egressServiceMap: + type: array + items: + $ref: '#/components/schemas/EgressService' + description: |- + External Process configuration. + NOTE: Only valid if 'isExternal' is set. + example: {} + IngressService: + type: object + properties: + name: + type: string + description: Service name (unique or multi-edge) + port: + type: integer + description: Internal service port number + externalPort: + type: integer + description: Externally-exposed unique service port in range (30000 - 32767) + protocol: + type: string + description: Service protocol (TCP or UDP) + description: Internal service exposed externally via specific port + EgressService: + type: object + properties: + name: + type: string + description: Service name + meSvcName: + type: string + description: "Multi-Edge service name, if any" + ip: + type: string + description: External node IP address + port: + type: integer + description: Service port number + protocol: + type: string + description: Service protocol (TCP or UDP) + description: External service exposed internally via specific port + UE: + title: UE + required: + - id + type: object + properties: + id: + type: string + description: The UE name. + example: "[\"Stationary UE\"]" + count: + type: integer + description: The number of UE instance. + example: + id: "[\"Stationary UE\"]" + SandboxMecServices: + title: SandboxMecServices + required: + - id + type: object + properties: + id: + type: string + description: The MEC service name. + example: "[\"Location (030)\"]" + service_id: + type: string + description: "When a MEC service is selected, this field contains a token\ + \ which shall be used in MEC service API URI." + example: + service_id: service_id + id: "[\"Location (030)\"]" + SandboxAppInstances: + title: SandboxAppInstances + required: + - id + type: object + properties: + id: + type: string + description: The application instance identifier. + example: "[\"c5f834ae-db0c-4eec-bdfe-3dfc55f91b4a\"]" + example: + id: "[\"c5f834ae-db0c-4eec-bdfe-3dfc55f91b4a\"]" + SandboxLogsSubscriptions: + title: SandboxLogsSubscriptions + required: + - callbackReference + type: object + properties: + callbackReference: + type: string + description: The callback to notify log messages. + example: "[\"http://my.callback.com/sandbox/logs/some-id\"]" + subscriptionReference: + type: string + description: The reference of the subscription. + example: "[\"37dd7ef4-c382-11ee-9301-5fe5aa3a97cf\"]" + example: + subscriptionReference: "[\"37dd7ef4-c382-11ee-9301-5fe5aa3a97cf\"]" + callbackReference: "[\"http://my.callback.com/sandbox/logs/some-id\"]" + Oauth: + type: object + properties: + user_code: + type: string + description: User code from the authentication provider + x-etsi-mec-cardinality: "1" + x-etsi-mec-origin-type: String + verification_uri: + type: string + description: Verification URI to go to and enter the user code in order + to authenticate + x-etsi-mec-cardinality: "1" + x-etsi-mec-origin-type: String + description: Sandbox object + example: {} + Namespace: + type: object + properties: + sandbox_name: + type: string + description: Name of the Sandbox + x-etsi-mec-cardinality: "1" + x-etsi-mec-origin-type: String + description: Namespace object + example: {} + ProblemDetails: + required: + - detail + - status + type: object + properties: + type: + type: string + description: | + A URI reference according to IETF RFC 3986 that identifies the problem type. It is encouraged that the URI provides human-readable documentation for the problem (e.g. using HTML) when dereferenced. When this member is not present, its value is assumed to be "about:blank". + format: URI + title: + type: string + description: | + A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization. If type is given and other than "about:blank", this attribute shall also be provided. A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4). + status: + type: integer + description: | + The HTTP status code for this occurrence of the problem. The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. + 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. It may yield further information if dereferenced. + format: URI + description: | + The definition of the general "ProblemDetails" data structure from IETF RFC 7807 is reproduced inthis structure. Compared to the general framework defined in IETF RFC 7807, the "status" and "detail" attributes are mandated to be included by the present document, to ensure that the response contains additional textual information about an error. IETF RFC 7807 foresees extensibility of the "ProblemDetails" type. It is possible that particular APIs in the present document, or particular implementations, define extensions to define additional attributes that provide more information about the error. The description column only provides some explanation of the meaning to Facilitate understanding of the design. For a full description, see IETF RFC 7807. + example: + instance: instance + detail: detail + type: type + title: title + status: 0 + ApplicationInfo: + required: + - name + - nodeName + type: object + properties: + id: + type: string + description: Application Instance UUID + name: + type: string + description: Application name + nodeName: + type: string + description: Name of node where application instance is running + type: + type: string + description: Application Type + enum: + - USER + - SYSTEM + persist: + type: boolean + description: Reserved for internal platform usage + description: MEC Application instance information + example: + id: 00afec52-f0b6-464e-a660-33568c0975b9 + name: MyAppName + nodeName: node1 + type: USER diff --git a/examples/demo9/golang/client/api_authorization.go b/examples/demo9/golang/client/api_authorization.go new file mode 100644 index 000000000..538f8ff61 --- /dev/null +++ b/examples/demo9/golang/client/api_authorization.go @@ -0,0 +1,264 @@ + +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +import ( + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + +// Linger please +var ( + _ context.Context +) + +type AuthorizationApiService service +/* +AuthorizationApiService Get the namespace against the User Code +Get the namespace against the User Code + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param userCode User Code obtained from the login endpoint + +*/ +func (a *AuthorizationApiService) GetNamespace(ctx context.Context, userCode string) (Namespace, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Namespace + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/namespace" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("user_code", parameterToString(userCode, "")) + // 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"} + + // 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 Namespace + 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 +} +/* +AuthorizationApiService Initiate OAuth login procedure and creates a MEC Sandbox instance +Initiate OAuth login procedure and creates a MEC Sandbox instance + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param provider Oauth provider +@return Sandbox +*/ +func (a *AuthorizationApiService) Login(ctx context.Context, provider string) (Oauth, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Oauth + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/login" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("provider", parameterToString(provider, "")) + // 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"} + + // 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 == 201 { + var v Oauth + 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 +} +/* +AuthorizationApiService Terminates User Session and delete the Sandbox instance +Terminates User Session and delete the Sandbox instance + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + +*/ +func (a *AuthorizationApiService) Logout(ctx context.Context, sandboxName string) (*http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/logout" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("sandbox_name", parameterToString(sandboxName, "")) + // 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 +} diff --git a/examples/demo9/golang/client/api_sandbox_app_instances.go b/examples/demo9/golang/client/api_sandbox_app_instances.go new file mode 100644 index 000000000..57bd0794a --- /dev/null +++ b/examples/demo9/golang/client/api_sandbox_app_instances.go @@ -0,0 +1,270 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * 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" +) + +// Linger please +var ( + _ context.Context +) + +type SandboxAppInstancesApiService service + +/* +SandboxAppInstancesApiService Delete an existing application instance +This method removes an existing application instance + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + * @param appInstanceId It uniquely identifies a MEC application instance identifier + +*/ +func (a *SandboxAppInstancesApiService) SandboxAppInstancesDELETE(ctx context.Context, sandboxName string, appInstanceId 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 + "/sandboxAppInstances/{sandbox_name}/{app_instance_id}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -1) + localVarPath = strings.Replace(localVarPath, "{"+"app_instance_id"+"}", fmt.Sprintf("%v", appInstanceId), -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 +} + +/* +SandboxAppInstancesApiService Get the list of the available application instance identifiers +This method retrieves the list of the available application instance identifiers + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier +@return []ApplicationInfo +*/ +func (a *SandboxAppInstancesApiService) SandboxAppInstancesGET(ctx context.Context, sandboxName string) ([]ApplicationInfo, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []ApplicationInfo + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxAppInstances/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -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"} + + // 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 []ApplicationInfo + 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 +} + +/* +SandboxAppInstancesApiService Create a new application instance identifier +This method creates a new application instance + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param body Pet to add to the store + * @param sandboxName Sandbox identifier +@return []ApplicationInfo +*/ +func (a *SandboxAppInstancesApiService) SandboxAppInstancesPOST(ctx context.Context, body ApplicationInfo, sandboxName string) ([]ApplicationInfo, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []ApplicationInfo + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxAppInstances/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -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 []ApplicationInfo + 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/examples/demo9/golang/client/api_sandbox_logs_subscriptions.go b/examples/demo9/golang/client/api_sandbox_logs_subscriptions.go new file mode 100644 index 000000000..5aeca5c0e --- /dev/null +++ b/examples/demo9/golang/client/api_sandbox_logs_subscriptions.go @@ -0,0 +1,182 @@ + +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +import ( + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "fmt" +) + +// Linger please +var ( + _ context.Context +) + +type SandboxLogsSubscriptionsApiService service +/* +SandboxLogsSubscriptionsApiService Subscription to receive logs from the sandbox +This method is used to receive logs from the sandbox. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + * @param subscriptionReference It uniquely identifies subscription reference to receive logs from the sandbox + +*/ +func (a *SandboxLogsSubscriptionsApiService) SandboxLogsSubscriptionsDELETE(ctx context.Context, sandboxName string, subscriptionReference 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 + "/sandboxLogsSubscriptions/{sandbox_name}/{subscription_reference}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -1) + localVarPath = strings.Replace(localVarPath, "{"+"subscription_reference"+"}", fmt.Sprintf("%v", subscriptionReference), -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 +} +/* +SandboxLogsSubscriptionsApiService Subscription to receive logs from the sandbox +This method is used to receive logs from the sandbox. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier +@return []SandboxLogsSubscriptions +*/ +func (a *SandboxLogsSubscriptionsApiService) SandboxLogsSubscriptionsPOST(ctx context.Context, sandboxName string) ([]SandboxLogsSubscriptions, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []SandboxLogsSubscriptions + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxLogsSubscriptions/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -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"} + + // 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 == 201 { + var v []SandboxLogsSubscriptions + 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/examples/demo9/golang/client/api_sandbox_mec_services.go b/examples/demo9/golang/client/api_sandbox_mec_services.go new file mode 100644 index 000000000..b396e6b43 --- /dev/null +++ b/examples/demo9/golang/client/api_sandbox_mec_services.go @@ -0,0 +1,112 @@ + +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +import ( + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "fmt" +) + +// Linger please +var ( + _ context.Context +) + +type SandboxMECServicesApiService service +/* +SandboxMECServicesApiService Get the list of the available MEC services +This method retrieves the list of the available MEC services. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier +@return []SandboxMecServices +*/ +func (a *SandboxMECServicesApiService) SandboxMecServicesGET(ctx context.Context, sandboxName string) ([]SandboxMecServices, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []SandboxMecServices + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxMecServices/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -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"} + + // 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 []SandboxMecServices + 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/examples/demo9/golang/client/api_sandbox_network_scenarios.go b/examples/demo9/golang/client/api_sandbox_network_scenarios.go new file mode 100644 index 000000000..724576071 --- /dev/null +++ b/examples/demo9/golang/client/api_sandbox_network_scenarios.go @@ -0,0 +1,344 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * 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" +) + +// Linger please +var ( + _ context.Context +) + +type SandboxNetworkScenariosApiService service + +/* +SandboxNetworkScenariosApiService Get description of a Network Scenario to be used. +This method retrive description of a the network scenario + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + * @param networkScenarioId Network scenario to retrieve +@return []Scenario +*/ +func (a *SandboxNetworkScenariosApiService) SandboxIndividualNetworkScenariosGET(ctx context.Context, sandboxName string, networkScenarioId string) ([]Scenario, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []Scenario + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxNetworkScenarios/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("network_scenario_id", parameterToString(networkScenarioId, "")) + // 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"} + + // 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 []Scenario + 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 +} + +/* +SandboxNetworkScenariosApiService Deactivate the Network Scenario. +This method deactivates the network scenario + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + * @param networkScenarioId Network scenario to be used + +*/ +func (a *SandboxNetworkScenariosApiService) SandboxNetworkScenarioDELETE(ctx context.Context, sandboxName string, networkScenarioId 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 + "/sandboxNetworkScenarios/{sandbox_name}/{network_scenario_id}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -1) + localVarPath = strings.Replace(localVarPath, "{"+"network_scenario_id"+"}", fmt.Sprintf("%v", networkScenarioId), -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 + } + + //fmt.Println("SandboxNetworkScenarioDELETE: r: ", r) + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarHttpResponse, err + } + //fmt.Println("SandboxNetworkScenarioDELETE: localVarHttpResponse: ", localVarHttpResponse) + + 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 +} + +/* +SandboxNetworkScenariosApiService Selects the Network Scenario to be activated. +This method selects the network scenario to be activated. This request initiates the creation of necessary MEC services for specific network scenario + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + * @param networkScenarioId Network scenario to be used + +*/ +func (a *SandboxNetworkScenariosApiService) SandboxNetworkScenarioPOST(ctx context.Context, sandboxName string, networkScenarioId string) (*http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxNetworkScenarios/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("network_scenario_id", parameterToString(networkScenarioId, "")) + // 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 + } + + //fmt.Println("SandboxNetworkScenarioPOST: r: ", r) + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarHttpResponse, err + } + //fmt.Println("SandboxNetworkScenarioPOST: localVarHttpResponse: ", localVarHttpResponse) + + 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 +} + +/* +SandboxNetworkScenariosApiService Get the list of the available network scenarios +This method retrieves the list of the available network scenarios. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier +@return []SandboxNetworkScenario +*/ +func (a *SandboxNetworkScenariosApiService) SandboxNetworkScenariosGET(ctx context.Context, sandboxName string) ([]SandboxNetworkScenario, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []SandboxNetworkScenario + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxNetworkScenarios" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("sandbox_name", parameterToString(sandboxName, "")) + // 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"} + + // 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 + } + + //fmt.Println("SandboxNetworkScenariosGET: r: ", r) + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + //fmt.Println("SandboxNetworkScenariosGET: localVarHttpResponse: ", localVarHttpResponse) + + 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 []SandboxNetworkScenario + 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/examples/demo9/golang/client/api_sandbox_ue_controller.go b/examples/demo9/golang/client/api_sandbox_ue_controller.go new file mode 100644 index 000000000..1368576b9 --- /dev/null +++ b/examples/demo9/golang/client/api_sandbox_ue_controller.go @@ -0,0 +1,184 @@ + +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +import ( + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "fmt" +) + +// Linger please +var ( + _ context.Context +) + +type SandboxUEControllerApiService service +/* +SandboxUEControllerApiService Get the list of the available UEs (e.g. \"Stationary UE\") +This method retrieves the list of the available available UEs. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier +@return []Ue +*/ +func (a *SandboxUEControllerApiService) SandboxUeControllerGET(ctx context.Context, sandboxName string) ([]Ue, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue []Ue + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxUeController/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -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"} + + // 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 []Ue + 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 +} +/* +SandboxUEControllerApiService set the new value of the UE +This method sets the new value of the UE. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param sandboxName Sandbox identifier + * @param userEquipmentId User equipmenet identifier + * @param userEquipmentValue It uniquely identifies a UE to set the new value + +*/ +func (a *SandboxUEControllerApiService) SandboxUeControllerPATCH(ctx context.Context, sandboxName string, userEquipmentId string, userEquipmentValue int32) (*http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Patch") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/sandboxUeController/{sandbox_name}" + localVarPath = strings.Replace(localVarPath, "{"+"sandbox_name"+"}", fmt.Sprintf("%v", sandboxName), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("user_equipment_id", parameterToString(userEquipmentId, "")) + localVarQueryParams.Add("user_equipment_value", parameterToString(userEquipmentValue, "")) + // 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 +} diff --git a/examples/demo9/golang/client/client.go b/examples/demo9/golang/client/client.go new file mode 100644 index 000000000..690d03e5e --- /dev/null +++ b/examples/demo9/golang/client/client.go @@ -0,0 +1,490 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +import ( + "bytes" + "context" + //"crypto/tls" + "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 Sandbox API API v0.0.7 +// 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 + + AuthorizationApi *AuthorizationApiService + + SandboxAppInstancesApi *SandboxAppInstancesApiService + + SandboxLogsSubscriptionsApi *SandboxLogsSubscriptionsApiService + + SandboxMECServicesApi *SandboxMECServicesApiService + + SandboxNetworkScenariosApi *SandboxNetworkScenariosApiService + + SandboxUEControllerApi *SandboxUEControllerApiService +} + +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.AuthorizationApi = (*AuthorizationApiService)(&c.common) + c.SandboxAppInstancesApi = (*SandboxAppInstancesApiService)(&c.common) + c.SandboxLogsSubscriptionsApi = (*SandboxLogsSubscriptionsApiService)(&c.common) + c.SandboxMECServicesApi = (*SandboxMECServicesApiService)(&c.common) + c.SandboxNetworkScenariosApi = (*SandboxNetworkScenariosApiService)(&c.common) + c.SandboxUEControllerApi = (*SandboxUEControllerApiService)(&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/examples/demo9/golang/client/configuration.go b/examples/demo9/golang/client/configuration.go new file mode 100644 index 000000000..f3f36dcce --- /dev/null +++ b/examples/demo9/golang/client/configuration.go @@ -0,0 +1,72 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * 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: "http://localhost/sandbox-api/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/examples/demo9/golang/client/docs/ApplicationInfo.md b/examples/demo9/golang/client/docs/ApplicationInfo.md new file mode 100644 index 000000000..1c7a5def7 --- /dev/null +++ b/examples/demo9/golang/client/docs/ApplicationInfo.md @@ -0,0 +1,13 @@ +# ApplicationInfo + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | Application Instance UUID | [optional] [default to null] +**Name** | **string** | Application name | [default to null] +**NodeName** | **string** | Name of node where application instance is running | [default to null] +**Type_** | **string** | Application Type | [optional] [default to null] +**Persist** | **bool** | Reserved for internal platform usage | [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/examples/demo9/golang/client/docs/AuthorizationApi.md b/examples/demo9/golang/client/docs/AuthorizationApi.md new file mode 100644 index 000000000..7baf4f30a --- /dev/null +++ b/examples/demo9/golang/client/docs/AuthorizationApi.md @@ -0,0 +1,65 @@ +# {{classname}} + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**Login**](AuthorizationApi.md#Login) | **Post** /login | Initiate OAuth login procedure and creates a MEC Sandbox instance +[**Logout**](AuthorizationApi.md#Logout) | **Post** /logout | Terminates User Session and delete the Sandbox instance + +# **Login** +> Sandbox Login(ctx, provider) +Initiate OAuth login procedure and creates a MEC Sandbox instance + +Initiate OAuth login procedure and creates a MEC Sandbox instance + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **provider** | **string**| Oauth provider | + +### Return type + +[**Sandbox**](Sandbox.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **Logout** +> Logout(ctx, sandboxName) +Terminates User Session and delete the Sandbox instance + +Terminates User Session and delete the Sandbox instance + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + +### 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) + diff --git a/examples/demo9/golang/client/docs/CellularDomainConfig.md b/examples/demo9/golang/client/docs/CellularDomainConfig.md new file mode 100644 index 000000000..8367435a4 --- /dev/null +++ b/examples/demo9/golang/client/docs/CellularDomainConfig.md @@ -0,0 +1,11 @@ +# CellularDomainConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Mnc** | **string** | Mobile Network Code part of PLMN identity as defined in ETSI TS 136 413 | [optional] [default to null] +**Mcc** | **string** | Mobile Country Code part of PLMN identity as defined in ETSI TS 136 413 | [optional] [default to null] +**DefaultCellId** | **string** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 if no cellId is defined for the cell or if not applicable | [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/examples/demo9/golang/client/docs/CellularPoaConfig.md b/examples/demo9/golang/client/docs/CellularPoaConfig.md new file mode 100644 index 000000000..0f5fa55b4 --- /dev/null +++ b/examples/demo9/golang/client/docs/CellularPoaConfig.md @@ -0,0 +1,9 @@ +# CellularPoaConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**CellId** | **string** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell | [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/examples/demo9/golang/client/docs/ConnectivityConfig.md b/examples/demo9/golang/client/docs/ConnectivityConfig.md new file mode 100644 index 000000000..4c40b58d7 --- /dev/null +++ b/examples/demo9/golang/client/docs/ConnectivityConfig.md @@ -0,0 +1,9 @@ +# ConnectivityConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Model** | **string** | Connectivity Model: <li>OPEN: Any node in the scenario can communicate with any node <li>PDU: Terminal nodes (UE) require a PDU session to the target DN | [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/examples/demo9/golang/client/docs/CpuConfig.md b/examples/demo9/golang/client/docs/CpuConfig.md new file mode 100644 index 000000000..83e32983f --- /dev/null +++ b/examples/demo9/golang/client/docs/CpuConfig.md @@ -0,0 +1,10 @@ +# CpuConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Min** | **float32** | Minimum requested CPU | [optional] [default to null] +**Max** | **float32** | Maximum requested CPU | [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/examples/demo9/golang/client/docs/D2dConfig.md b/examples/demo9/golang/client/docs/D2dConfig.md new file mode 100644 index 000000000..3876c8848 --- /dev/null +++ b/examples/demo9/golang/client/docs/D2dConfig.md @@ -0,0 +1,10 @@ +# D2dConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**D2dMaxDistance** | **float64** | Maximum distance for D2D. Default distance is 100m | [optional] [default to null] +**DisableD2dViaNetwork** | **bool** | Enable-Disable D2D via network. Default value is false | [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/examples/demo9/golang/client/docs/Deployment.md b/examples/demo9/golang/client/docs/Deployment.md new file mode 100644 index 000000000..cd15f49ca --- /dev/null +++ b/examples/demo9/golang/client/docs/Deployment.md @@ -0,0 +1,18 @@ +# Deployment + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**NetChar** | [***NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] [default to null] +**Connectivity** | [***ConnectivityConfig**](ConnectivityConfig.md) | | [optional] [default to null] +**D2d** | [***D2dConfig**](D2dConfig.md) | | [optional] [default to null] +**InterDomainLatency** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] [default to null] +**InterDomainLatencyVariation** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] [default to null] +**InterDomainThroughput** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] [default to null] +**InterDomainPacketLoss** | **float64** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] [default to null] +**Meta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**UserMeta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**Domains** | [**[]Domain**](Domain.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/examples/demo9/golang/client/docs/DnConfig.md b/examples/demo9/golang/client/docs/DnConfig.md new file mode 100644 index 000000000..3e114f2ff --- /dev/null +++ b/examples/demo9/golang/client/docs/DnConfig.md @@ -0,0 +1,11 @@ +# DnConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Dnn** | **string** | Data Network Name | [optional] [default to null] +**Ladn** | **bool** | true: Data network serves local area only false: Data network is not limited to local area | [optional] [default to null] +**Ecsp** | **string** | Edge Compute Service Provider | [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/examples/demo9/golang/client/docs/Domain.md b/examples/demo9/golang/client/docs/Domain.md new file mode 100644 index 000000000..df60d2042 --- /dev/null +++ b/examples/demo9/golang/client/docs/Domain.md @@ -0,0 +1,20 @@ +# Domain + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | Unique domain ID | [optional] [default to null] +**Name** | **string** | Domain name | [optional] [default to null] +**Type_** | **string** | Domain type | [optional] [default to null] +**NetChar** | [***NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] [default to null] +**InterZoneLatency** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] [default to null] +**InterZoneLatencyVariation** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] [default to null] +**InterZoneThroughput** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] [default to null] +**InterZonePacketLoss** | **float64** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] [default to null] +**Meta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**UserMeta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**CellularDomainConfig** | [***CellularDomainConfig**](CellularDomainConfig.md) | | [optional] [default to null] +**Zones** | [**[]Zone**](Zone.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/examples/demo9/golang/client/docs/EgressService.md b/examples/demo9/golang/client/docs/EgressService.md new file mode 100644 index 000000000..ae3680f97 --- /dev/null +++ b/examples/demo9/golang/client/docs/EgressService.md @@ -0,0 +1,13 @@ +# EgressService + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Name** | **string** | Service name | [optional] [default to null] +**MeSvcName** | **string** | Multi-Edge service name, if any | [optional] [default to null] +**Ip** | **string** | External node IP address | [optional] [default to null] +**Port** | **int32** | Service port number | [optional] [default to null] +**Protocol** | **string** | Service protocol (TCP or UDP) | [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/examples/demo9/golang/client/docs/ExternalConfig.md b/examples/demo9/golang/client/docs/ExternalConfig.md new file mode 100644 index 000000000..729b6bded --- /dev/null +++ b/examples/demo9/golang/client/docs/ExternalConfig.md @@ -0,0 +1,10 @@ +# ExternalConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**IngressServiceMap** | [**[]IngressService**](IngressService.md) | | [optional] [default to null] +**EgressServiceMap** | [**[]EgressService**](EgressService.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/examples/demo9/golang/client/docs/GeoData.md b/examples/demo9/golang/client/docs/GeoData.md new file mode 100644 index 000000000..34f791768 --- /dev/null +++ b/examples/demo9/golang/client/docs/GeoData.md @@ -0,0 +1,15 @@ +# GeoData + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Location** | [***Point**](Point.md) | | [optional] [default to null] +**Radius** | **float64** | Optional - Radius (in meters) around the location | [optional] [default to null] +**Path** | [***LineString**](LineString.md) | | [optional] [default to null] +**EopMode** | **string** | End-of-Path mode: <li>LOOP: When path endpoint is reached, start over from the beginning <li>REVERSE: When path endpoint is reached, return on the reverse path | [optional] [default to null] +**Velocity** | **float64** | Speed of movement along path in m/s | [optional] [default to null] +**D2dInRange** | **[]string** | | [optional] [default to null] +**PoaInRange** | **[]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/examples/demo9/golang/client/docs/GpuConfig.md b/examples/demo9/golang/client/docs/GpuConfig.md new file mode 100644 index 000000000..74ea3c7fb --- /dev/null +++ b/examples/demo9/golang/client/docs/GpuConfig.md @@ -0,0 +1,10 @@ +# GpuConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Type_** | **string** | Requested GPU type | [optional] [default to null] +**Count** | **int32** | Number of GPUs requested | [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/examples/demo9/golang/client/docs/IngressService.md b/examples/demo9/golang/client/docs/IngressService.md new file mode 100644 index 000000000..7a36f7291 --- /dev/null +++ b/examples/demo9/golang/client/docs/IngressService.md @@ -0,0 +1,12 @@ +# IngressService + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Name** | **string** | Service name (unique or multi-edge) | [optional] [default to null] +**Port** | **int32** | Internal service port number | [optional] [default to null] +**ExternalPort** | **int32** | Externally-exposed unique service port in range (30000 - 32767) | [optional] [default to null] +**Protocol** | **string** | Service protocol (TCP or UDP) | [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/examples/demo9/golang/client/docs/LineString.md b/examples/demo9/golang/client/docs/LineString.md new file mode 100644 index 000000000..34db0599e --- /dev/null +++ b/examples/demo9/golang/client/docs/LineString.md @@ -0,0 +1,10 @@ +# LineString + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Type_** | **string** | Must be LineString | [default to null] +**Coordinates** | [**[][]float64**](array.md) | For a LineString, coordinates is an array of two or more positions; a position is an array of two decimal numbers (longitude and latitude precisely in that order) | [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/examples/demo9/golang/client/docs/MemoryConfig.md b/examples/demo9/golang/client/docs/MemoryConfig.md new file mode 100644 index 000000000..a72369433 --- /dev/null +++ b/examples/demo9/golang/client/docs/MemoryConfig.md @@ -0,0 +1,10 @@ +# MemoryConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Min** | **int32** | Minimum requested memory | [optional] [default to null] +**Max** | **int32** | Maximum requested memory | [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/examples/demo9/golang/client/docs/NetworkCharacteristics.md b/examples/demo9/golang/client/docs/NetworkCharacteristics.md new file mode 100644 index 000000000..277d6b1fd --- /dev/null +++ b/examples/demo9/golang/client/docs/NetworkCharacteristics.md @@ -0,0 +1,15 @@ +# NetworkCharacteristics + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Latency** | **int32** | Latency in ms | [optional] [default to null] +**LatencyVariation** | **int32** | Latency variation in ms | [optional] [default to null] +**LatencyDistribution** | **string** | Latency distribution. Can only be set in the Scenario Deployment network characteristics, ignored otherwise. Latency distribution is set for the whole network and applied to every end-to-end traffic flows. Default value is 'Normal' distribution. | [optional] [default to null] +**Throughput** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by throughputUl and throughputDl | [optional] [default to null] +**ThroughputDl** | **int32** | Downlink throughput limit in Mbps | [optional] [default to null] +**ThroughputUl** | **int32** | Uplink throughput limit in Mbps | [optional] [default to null] +**PacketLoss** | **float64** | Packet loss percentage | [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/examples/demo9/golang/client/docs/NetworkLocation.md b/examples/demo9/golang/client/docs/NetworkLocation.md new file mode 100644 index 000000000..1fad2ab71 --- /dev/null +++ b/examples/demo9/golang/client/docs/NetworkLocation.md @@ -0,0 +1,24 @@ +# NetworkLocation + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | Unique network location ID | [optional] [default to null] +**Name** | **string** | Network location name | [optional] [default to null] +**Type_** | **string** | Network location type | [optional] [default to null] +**NetChar** | [***NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] [default to null] +**TerminalLinkLatency** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] [default to null] +**TerminalLinkLatencyVariation** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] [default to null] +**TerminalLinkThroughput** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] [default to null] +**TerminalLinkPacketLoss** | **float64** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] [default to null] +**Meta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**UserMeta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**CellularPoaConfig** | [***CellularPoaConfig**](CellularPoaConfig.md) | | [optional] [default to null] +**Poa4GConfig** | [***Poa4GConfig**](Poa4GConfig.md) | | [optional] [default to null] +**Poa5GConfig** | [***Poa5GConfig**](Poa5GConfig.md) | | [optional] [default to null] +**PoaWifiConfig** | [***PoaWifiConfig**](PoaWifiConfig.md) | | [optional] [default to null] +**GeoData** | [***GeoData**](GeoData.md) | | [optional] [default to null] +**PhysicalLocations** | [**[]PhysicalLocation**](PhysicalLocation.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/examples/demo9/golang/client/docs/PhysicalLocation.md b/examples/demo9/golang/client/docs/PhysicalLocation.md new file mode 100644 index 000000000..01cf0a8a0 --- /dev/null +++ b/examples/demo9/golang/client/docs/PhysicalLocation.md @@ -0,0 +1,27 @@ +# PhysicalLocation + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | Unique physical location ID | [optional] [default to null] +**Name** | **string** | Physical location name | [optional] [default to null] +**Type_** | **string** | Physical location type | [optional] [default to null] +**IsExternal** | **bool** | true: Physical location is external to MEEP false: Physical location is internal to MEEP | [optional] [default to null] +**GeoData** | [***GeoData**](GeoData.md) | | [optional] [default to null] +**NetworkLocationsInRange** | **[]string** | | [optional] [default to null] +**Connected** | **bool** | true: Physical location has network connectivity false: Physical location has no network connectivity | [optional] [default to null] +**Wireless** | **bool** | true: Physical location uses a wireless connection false: Physical location uses a wired connection | [optional] [default to null] +**WirelessType** | **string** | Prioritized, comma-separated list of supported wireless connection types. Default priority if not specififed is 'wifi,5g,4g,other'. Wireless connection types: - 4g - 5g - wifi - other | [optional] [default to null] +**DataNetwork** | [***DnConfig**](DNConfig.md) | | [optional] [default to null] +**Meta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**UserMeta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**Processes** | [**[]Process**](Process.md) | | [optional] [default to null] +**NetChar** | [***NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] [default to null] +**LinkLatency** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] [default to null] +**LinkLatencyVariation** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] [default to null] +**LinkThroughput** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] [default to null] +**LinkPacketLoss** | **float64** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] [default to null] +**MacId** | **string** | Physical location MAC Address | [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/examples/demo9/golang/client/docs/Poa4GConfig.md b/examples/demo9/golang/client/docs/Poa4GConfig.md new file mode 100644 index 000000000..b3c288bb4 --- /dev/null +++ b/examples/demo9/golang/client/docs/Poa4GConfig.md @@ -0,0 +1,9 @@ +# Poa4GConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**CellId** | **string** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell | [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/examples/demo9/golang/client/docs/Poa5GConfig.md b/examples/demo9/golang/client/docs/Poa5GConfig.md new file mode 100644 index 000000000..cb74001c5 --- /dev/null +++ b/examples/demo9/golang/client/docs/Poa5GConfig.md @@ -0,0 +1,9 @@ +# Poa5GConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**CellId** | **string** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the NR serving the cell | [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/examples/demo9/golang/client/docs/PoaWifiConfig.md b/examples/demo9/golang/client/docs/PoaWifiConfig.md new file mode 100644 index 000000000..91c4a1c3c --- /dev/null +++ b/examples/demo9/golang/client/docs/PoaWifiConfig.md @@ -0,0 +1,9 @@ +# PoaWifiConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**MacId** | **string** | WIFI POA MAC Address | [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/examples/demo9/golang/client/docs/Point.md b/examples/demo9/golang/client/docs/Point.md new file mode 100644 index 000000000..ccf42e60c --- /dev/null +++ b/examples/demo9/golang/client/docs/Point.md @@ -0,0 +1,10 @@ +# Point + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Type_** | **string** | Must be Point | [default to null] +**Coordinates** | **[]float64** | For a Point, coordinates MUST be an array of two decimal numbers; longitude and latitude precisely in that order | [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/examples/demo9/golang/client/docs/ProblemDetails.md b/examples/demo9/golang/client/docs/ProblemDetails.md new file mode 100644 index 000000000..b679201f2 --- /dev/null +++ b/examples/demo9/golang/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. It is encouraged that the URI provides human-readable documentation for the problem (e.g. using HTML) when dereferenced. When this member is not present, its value is assumed to be \"about:blank\". | [optional] [default to null] +**Title** | **string** | A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization. If type is given and other than \"about:blank\", this attribute shall also be provided. A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4). | [optional] [default to null] +**Status** | **int32** | The HTTP status code for this occurrence of the problem. The HTTP status code ([RFC7231], Section 6) generated by the origin server 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. It may yield further information if dereferenced. | [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/examples/demo9/golang/client/docs/Process.md b/examples/demo9/golang/client/docs/Process.md new file mode 100644 index 000000000..99a690696 --- /dev/null +++ b/examples/demo9/golang/client/docs/Process.md @@ -0,0 +1,33 @@ +# Process + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | Unique process ID | [optional] [default to null] +**Name** | **string** | Process name | [optional] [default to null] +**Type_** | **string** | Process type | [optional] [default to null] +**IsExternal** | **bool** | true: process is external to MEEP false: process is internal to MEEP | [optional] [default to null] +**Image** | **string** | Docker image to deploy inside MEEP | [optional] [default to null] +**Environment** | **string** | Environment variables using the format NAME=\"value\",NAME=\"value\",NAME=\"value\" | [optional] [default to null] +**CommandArguments** | **string** | Arguments to command executable | [optional] [default to null] +**CommandExe** | **string** | Executable to invoke at container start up | [optional] [default to null] +**ServiceConfig** | [***ServiceConfig**](ServiceConfig.md) | | [optional] [default to null] +**GpuConfig** | [***GpuConfig**](GpuConfig.md) | | [optional] [default to null] +**MemoryConfig** | [***MemoryConfig**](MemoryConfig.md) | | [optional] [default to null] +**CpuConfig** | [***CpuConfig**](CpuConfig.md) | | [optional] [default to null] +**ExternalConfig** | [***ExternalConfig**](ExternalConfig.md) | | [optional] [default to null] +**Status** | **string** | Process status | [optional] [default to null] +**UserChartLocation** | **string** | Chart location for the deployment of the chart provided by the user | [optional] [default to null] +**UserChartAlternateValues** | **string** | Chart values.yaml file location for the deployment of the chart provided by the user | [optional] [default to null] +**UserChartGroup** | **string** | Chart supplemental information related to the group (service) | [optional] [default to null] +**Meta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**UserMeta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**NetChar** | [***NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] [default to null] +**AppLatency** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] [default to null] +**AppLatencyVariation** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] [default to null] +**AppThroughput** | **int32** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] [default to null] +**AppPacketLoss** | **float64** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] [default to null] +**PlacementId** | **string** | Identifier used for process placement in AdvantEDGE cluster | [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/examples/demo9/golang/client/docs/Sandbox.md b/examples/demo9/golang/client/docs/Sandbox.md new file mode 100644 index 000000000..4d7cee4c3 --- /dev/null +++ b/examples/demo9/golang/client/docs/Sandbox.md @@ -0,0 +1,9 @@ +# Sandbox + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Name** | **string** | Sandbox name | [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/examples/demo9/golang/client/docs/SandboxAppInstances.md b/examples/demo9/golang/client/docs/SandboxAppInstances.md new file mode 100644 index 000000000..01b49cd20 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxAppInstances.md @@ -0,0 +1,9 @@ +# SandboxAppInstances + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | The application instance identifier. | [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/examples/demo9/golang/client/docs/SandboxAppInstancesApi.md b/examples/demo9/golang/client/docs/SandboxAppInstancesApi.md new file mode 100644 index 000000000..03415aa39 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxAppInstancesApi.md @@ -0,0 +1,96 @@ +# {{classname}} + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**SandboxAppInstancesDELETE**](SandboxAppInstancesApi.md#SandboxAppInstancesDELETE) | **Delete** /sandboxAppInstances/{sandbox_name}/{app_instance_id} | Delete an existing application instance +[**SandboxAppInstancesGET**](SandboxAppInstancesApi.md#SandboxAppInstancesGET) | **Get** /sandboxAppInstances/{sandbox_name} | Get the list of the available application instance identifiers +[**SandboxAppInstancesPOST**](SandboxAppInstancesApi.md#SandboxAppInstancesPOST) | **Post** /sandboxAppInstances/{sandbox_name} | Create a new application instance identifier + +# **SandboxAppInstancesDELETE** +> SandboxAppInstancesDELETE(ctx, sandboxName, appInstanceId) +Delete an existing application instance + +This method removes an existing application instance + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + **appInstanceId** | **string**| It uniquely identifies a MEC application instance identifier | + +### 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) + +# **SandboxAppInstancesGET** +> []SandboxAppInstances SandboxAppInstancesGET(ctx, sandboxName) +Get the list of the available application instance identifiers + +This method retrieves the list of the available application instance identifiers + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + +### Return type + +[**[]SandboxAppInstances**](SandboxAppInstances.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **SandboxAppInstancesPOST** +> []ApplicationInfo SandboxAppInstancesPOST(ctx, body, sandboxName) +Create a new application instance identifier + +This method creates a new application instance + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **body** | [**ApplicationInfo**](ApplicationInfo.md)| Pet to add to the store | + **sandboxName** | **string**| Sandbox identifier | + +### Return type + +[**[]ApplicationInfo**](ApplicationInfo.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) + diff --git a/examples/demo9/golang/client/docs/SandboxLogsSubscriptions.md b/examples/demo9/golang/client/docs/SandboxLogsSubscriptions.md new file mode 100644 index 000000000..47166a649 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxLogsSubscriptions.md @@ -0,0 +1,10 @@ +# SandboxLogsSubscriptions + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**CallbackReference** | **string** | The callback to notify log messages. | [default to null] +**SubscriptionReference** | **string** | The reference of the subscription. | [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/examples/demo9/golang/client/docs/SandboxLogsSubscriptionsApi.md b/examples/demo9/golang/client/docs/SandboxLogsSubscriptionsApi.md new file mode 100644 index 000000000..173d9e171 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxLogsSubscriptionsApi.md @@ -0,0 +1,66 @@ +# {{classname}} + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**SandboxLogsSubscriptionsDELETE**](SandboxLogsSubscriptionsApi.md#SandboxLogsSubscriptionsDELETE) | **Delete** /sandboxLogsSubscriptions/{sandbox_name}/{subscription_reference} | Subscription to receive logs from the sandbox +[**SandboxLogsSubscriptionsPOST**](SandboxLogsSubscriptionsApi.md#SandboxLogsSubscriptionsPOST) | **Post** /sandboxLogsSubscriptions/{sandbox_name} | Subscription to receive logs from the sandbox + +# **SandboxLogsSubscriptionsDELETE** +> SandboxLogsSubscriptionsDELETE(ctx, sandboxName, subscriptionReference) +Subscription to receive logs from the sandbox + +This method is used to receive logs from the sandbox. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + **subscriptionReference** | **string**| It uniquely identifies subscription reference to receive logs from the sandbox | + +### 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) + +# **SandboxLogsSubscriptionsPOST** +> []SandboxLogsSubscriptions SandboxLogsSubscriptionsPOST(ctx, sandboxName) +Subscription to receive logs from the sandbox + +This method is used to receive logs from the sandbox. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + +### Return type + +[**[]SandboxLogsSubscriptions**](SandboxLogsSubscriptions.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + diff --git a/examples/demo9/golang/client/docs/SandboxMECServicesApi.md b/examples/demo9/golang/client/docs/SandboxMECServicesApi.md new file mode 100644 index 000000000..f006ee5a5 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxMECServicesApi.md @@ -0,0 +1,36 @@ +# {{classname}} + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**SandboxMecServicesGET**](SandboxMECServicesApi.md#SandboxMecServicesGET) | **Get** /sandboxMecServices/{sandbox_name} | Get the list of the available MEC services + +# **SandboxMecServicesGET** +> []SandboxMecServices SandboxMecServicesGET(ctx, sandboxName) +Get the list of the available MEC services + +This method retrieves the list of the available MEC services. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + +### Return type + +[**[]SandboxMecServices**](SandboxMecServices.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + diff --git a/examples/demo9/golang/client/docs/SandboxMecServices.md b/examples/demo9/golang/client/docs/SandboxMecServices.md new file mode 100644 index 000000000..4d1ddec04 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxMecServices.md @@ -0,0 +1,10 @@ +# SandboxMecServices + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | The MEC service name. | [default to null] +**ServiceId** | **string** | When a MEC service is selected, this field contains a token which shall be used in MEC service API URI. | [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/examples/demo9/golang/client/docs/SandboxNetworkScenario.md b/examples/demo9/golang/client/docs/SandboxNetworkScenario.md new file mode 100644 index 000000000..3f8a4d874 --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxNetworkScenario.md @@ -0,0 +1,9 @@ +# SandboxNetworkScenario + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | The network scenario name. | [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/examples/demo9/golang/client/docs/SandboxNetworkScenariosApi.md b/examples/demo9/golang/client/docs/SandboxNetworkScenariosApi.md new file mode 100644 index 000000000..53b8e66ac --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxNetworkScenariosApi.md @@ -0,0 +1,126 @@ +# {{classname}} + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**SandboxIndividualNetworkScenariosGET**](SandboxNetworkScenariosApi.md#SandboxIndividualNetworkScenariosGET) | **Get** /sandboxNetworkScenarios/{sandbox_name} | Get description of a Network Scenario to be used. +[**SandboxNetworkScenarioDELETE**](SandboxNetworkScenariosApi.md#SandboxNetworkScenarioDELETE) | **Delete** /sandboxNetworkScenarios/{sandbox_name}/{network_scenario_id} | Deactivate the Network Scenario. +[**SandboxNetworkScenarioPOST**](SandboxNetworkScenariosApi.md#SandboxNetworkScenarioPOST) | **Post** /sandboxNetworkScenarios/{sandbox_name} | Selects the Network Scenario to be activated. +[**SandboxNetworkScenariosGET**](SandboxNetworkScenariosApi.md#SandboxNetworkScenariosGET) | **Get** /sandboxNetworkScenarios | Get the list of the available network scenarios + +# **SandboxIndividualNetworkScenariosGET** +> []Scenario SandboxIndividualNetworkScenariosGET(ctx, sandboxName, networkScenarioId) +Get description of a Network Scenario to be used. + +This method retrive description of a the network scenario + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + **networkScenarioId** | **string**| Network scenario to retrieve | + +### Return type + +[**[]Scenario**](Scenario.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **SandboxNetworkScenarioDELETE** +> SandboxNetworkScenarioDELETE(ctx, sandboxName, networkScenarioId) +Deactivate the Network Scenario. + +This method deactivates the network scenario + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + **networkScenarioId** | **string**| Network scenario to be used | + +### 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) + +# **SandboxNetworkScenarioPOST** +> SandboxNetworkScenarioPOST(ctx, sandboxName, networkScenarioId) +Selects the Network Scenario to be activated. + +This method selects the network scenario to be activated. This request initiates the creation of necessary MEC services for specific network scenario + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + **networkScenarioId** | **string**| Network scenario to be used | + +### 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) + +# **SandboxNetworkScenariosGET** +> []SandboxNetworkScenario SandboxNetworkScenariosGET(ctx, sandboxName) +Get the list of the available network scenarios + +This method retrieves the list of the available network scenarios. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + +### Return type + +[**[]SandboxNetworkScenario**](SandboxNetworkScenario.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + diff --git a/examples/demo9/golang/client/docs/SandboxUEControllerApi.md b/examples/demo9/golang/client/docs/SandboxUEControllerApi.md new file mode 100644 index 000000000..6f20afcef --- /dev/null +++ b/examples/demo9/golang/client/docs/SandboxUEControllerApi.md @@ -0,0 +1,67 @@ +# {{classname}} + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**SandboxUeControllerGET**](SandboxUEControllerApi.md#SandboxUeControllerGET) | **Get** /sandboxUeController/{sandbox_name} | Get the list of the available UEs (e.g. \"Stationary UE\") +[**SandboxUeControllerPATCH**](SandboxUEControllerApi.md#SandboxUeControllerPATCH) | **Patch** /sandboxUeController/{sandbox_name} | set the new value of the UE + +# **SandboxUeControllerGET** +> []Ue SandboxUeControllerGET(ctx, sandboxName) +Get the list of the available UEs (e.g. \"Stationary UE\") + +This method retrieves the list of the available available UEs. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + +### Return type + +[**[]Ue**](UE.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **SandboxUeControllerPATCH** +> SandboxUeControllerPATCH(ctx, sandboxName, userEquipmentId, userEquipmentValue) +set the new value of the UE + +This method sets the new value of the UE. + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + **sandboxName** | **string**| Sandbox identifier | + **userEquipmentId** | **string**| User equipmenet identifier | + **userEquipmentValue** | **int32**| It uniquely identifies a UE to set the new value | + +### 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) + diff --git a/examples/demo9/golang/client/docs/Scenario.md b/examples/demo9/golang/client/docs/Scenario.md new file mode 100644 index 000000000..5c344aa59 --- /dev/null +++ b/examples/demo9/golang/client/docs/Scenario.md @@ -0,0 +1,14 @@ +# Scenario + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Version** | **string** | Scenario version | [optional] [default to null] +**Id** | **string** | Unique scenario ID | [optional] [default to null] +**Name** | **string** | Unique scenario name | [optional] [default to null] +**Description** | **string** | User description of the scenario. | [optional] [default to null] +**Config** | [***ScenarioConfig**](ScenarioConfig.md) | | [optional] [default to null] +**Deployment** | [***Deployment**](Deployment.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/examples/demo9/golang/client/docs/ScenarioConfig.md b/examples/demo9/golang/client/docs/ScenarioConfig.md new file mode 100644 index 000000000..38839d4fa --- /dev/null +++ b/examples/demo9/golang/client/docs/ScenarioConfig.md @@ -0,0 +1,10 @@ +# ScenarioConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Visualization** | **string** | Visualization configuration | [optional] [default to null] +**Other** | **string** | Other scenario configuration | [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/examples/demo9/golang/client/docs/ServiceConfig.md b/examples/demo9/golang/client/docs/ServiceConfig.md new file mode 100644 index 000000000..9cebfe125 --- /dev/null +++ b/examples/demo9/golang/client/docs/ServiceConfig.md @@ -0,0 +1,11 @@ +# ServiceConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Name** | **string** | Unique service name | [optional] [default to null] +**MeSvcName** | **string** | Multi-Edge service name, if any | [optional] [default to null] +**Ports** | [**[]ServicePort**](ServicePort.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/examples/demo9/golang/client/docs/ServicePort.md b/examples/demo9/golang/client/docs/ServicePort.md new file mode 100644 index 000000000..320211035 --- /dev/null +++ b/examples/demo9/golang/client/docs/ServicePort.md @@ -0,0 +1,11 @@ +# ServicePort + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Protocol** | **string** | Protocol that the application is using (TCP or UDP) | [optional] [default to null] +**Port** | **int32** | Port number that the service is listening on | [optional] [default to null] +**ExternalPort** | **int32** | External port number on which to expose the application (30000 - 32767) <li>Only one application allowed per external port <li>Scenario builder must configure to prevent conflicts | [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/examples/demo9/golang/client/docs/Ue.md b/examples/demo9/golang/client/docs/Ue.md new file mode 100644 index 000000000..ed3246b8e --- /dev/null +++ b/examples/demo9/golang/client/docs/Ue.md @@ -0,0 +1,9 @@ +# Ue + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | The UE name. | [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/examples/demo9/golang/client/docs/Zone.md b/examples/demo9/golang/client/docs/Zone.md new file mode 100644 index 000000000..8a0635a1b --- /dev/null +++ b/examples/demo9/golang/client/docs/Zone.md @@ -0,0 +1,27 @@ +# Zone + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Id** | **string** | Unique zone ID | [optional] [default to null] +**Name** | **string** | Zone name | [optional] [default to null] +**Type_** | **string** | Zone type | [optional] [default to null] +**NetChar** | [***NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] [default to null] +**InterFogLatency** | **int32** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterFogLatencyVariation** | **int32** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterFogThroughput** | **int32** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterFogPacketLoss** | **float64** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterEdgeLatency** | **int32** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterEdgeLatencyVariation** | **int32** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterEdgeThroughput** | **int32** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**InterEdgePacketLoss** | **float64** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] [default to null] +**EdgeFogLatency** | **int32** | **DEPRECATED** As of release 1.3.0, replaced by netChar latency | [optional] [default to null] +**EdgeFogLatencyVariation** | **int32** | **DEPRECATED** As of release 1.3.0, replaced by netChar latencyVariation | [optional] [default to null] +**EdgeFogThroughput** | **int32** | **DEPRECATED** As of release 1.3.0, replaced by netChar throughput | [optional] [default to null] +**EdgeFogPacketLoss** | **float64** | **DEPRECATED** As of release 1.3.0, replaced by netChar packetLoss | [optional] [default to null] +**Meta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**UserMeta** | **map[string]string** | Key/Value Pair Map (string, string) | [optional] [default to null] +**NetworkLocations** | [**[]NetworkLocation**](NetworkLocation.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/examples/demo9/golang/client/git_push.sh b/examples/demo9/golang/client/git_push.sh new file mode 100644 index 000000000..ae01b182a --- /dev/null +++ b/examples/demo9/golang/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/examples/demo9/golang/client/model_application_info.go b/examples/demo9/golang/client/model_application_info.go new file mode 100644 index 000000000..50dd3bd9a --- /dev/null +++ b/examples/demo9/golang/client/model_application_info.go @@ -0,0 +1,24 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// MEC Application instance information +type ApplicationInfo struct { + // Application Instance UUID + Id string `json:"id,omitempty"` + // Application name + Name string `json:"name"` + // Name of node where application instance is running + NodeName string `json:"nodeName"` + // Application Type + Type_ string `json:"type,omitempty"` + // Reserved for internal platform usage + Persist bool `json:"persist,omitempty"` +} diff --git a/examples/demo9/golang/client/model_cellular_domain_config.go b/examples/demo9/golang/client/model_cellular_domain_config.go new file mode 100644 index 000000000..63db45372 --- /dev/null +++ b/examples/demo9/golang/client/model_cellular_domain_config.go @@ -0,0 +1,20 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Cellular domain configuration information +type CellularDomainConfig struct { + // Mobile Network Code part of PLMN identity as defined in ETSI TS 136 413 + Mnc string `json:"mnc,omitempty"` + // Mobile Country Code part of PLMN identity as defined in ETSI TS 136 413 + Mcc string `json:"mcc,omitempty"` + // The E-UTRAN Cell Identity as defined in ETSI TS 136 413 if no cellId is defined for the cell or if not applicable + DefaultCellId string `json:"defaultCellId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_cellular_poa_config.go b/examples/demo9/golang/client/model_cellular_poa_config.go new file mode 100644 index 000000000..d0787b42d --- /dev/null +++ b/examples/demo9/golang/client/model_cellular_poa_config.go @@ -0,0 +1,16 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// **DEPRECATED** As of release 1.5.1, renamed to poa4GConfig +type CellularPoaConfig struct { + // The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell + CellId string `json:"cellId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_connectivity_config.go b/examples/demo9/golang/client/model_connectivity_config.go new file mode 100644 index 000000000..aa092c010 --- /dev/null +++ b/examples/demo9/golang/client/model_connectivity_config.go @@ -0,0 +1,15 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +type ConnectivityConfig struct { + // Connectivity Model:
  • OPEN: Any node in the scenario can communicate with any node
  • PDU: Terminal nodes (UE) require a PDU session to the target DN + Model string `json:"model,omitempty"` +} diff --git a/examples/demo9/golang/client/model_cpu_config.go b/examples/demo9/golang/client/model_cpu_config.go new file mode 100644 index 000000000..7537511c1 --- /dev/null +++ b/examples/demo9/golang/client/model_cpu_config.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// CPU configuration object +type CpuConfig struct { + // Minimum requested CPU + Min float32 `json:"min,omitempty"` + // Maximum requested CPU + Max float32 `json:"max,omitempty"` +} diff --git a/examples/demo9/golang/client/model_d2d_config.go b/examples/demo9/golang/client/model_d2d_config.go new file mode 100644 index 000000000..78a992bca --- /dev/null +++ b/examples/demo9/golang/client/model_d2d_config.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// D2D config +type D2dConfig struct { + // Maximum distance for D2D. Default distance is 100m + D2dMaxDistance float64 `json:"d2dMaxDistance,omitempty"` + // Enable-Disable D2D via network. Default value is false + DisableD2dViaNetwork bool `json:"disableD2dViaNetwork,omitempty"` +} diff --git a/examples/demo9/golang/client/model_deployment.go b/examples/demo9/golang/client/model_deployment.go new file mode 100644 index 000000000..575ba0fe5 --- /dev/null +++ b/examples/demo9/golang/client/model_deployment.go @@ -0,0 +1,30 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Network deployment object +type Deployment struct { + NetChar *NetworkCharacteristics `json:"netChar,omitempty"` + Connectivity *ConnectivityConfig `json:"connectivity,omitempty"` + D2d *D2dConfig `json:"d2d,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latency + InterDomainLatency int32 `json:"interDomainLatency,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation + InterDomainLatencyVariation int32 `json:"interDomainLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl + InterDomainThroughput int32 `json:"interDomainThroughput,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss + InterDomainPacketLoss float64 `json:"interDomainPacketLoss,omitempty"` + // Key/Value Pair Map (string, string) + Meta map[string]string `json:"meta,omitempty"` + // Key/Value Pair Map (string, string) + UserMeta map[string]string `json:"userMeta,omitempty"` + Domains []Domain `json:"domains,omitempty"` +} diff --git a/examples/demo9/golang/client/model_dn_config.go b/examples/demo9/golang/client/model_dn_config.go new file mode 100644 index 000000000..efd086d34 --- /dev/null +++ b/examples/demo9/golang/client/model_dn_config.go @@ -0,0 +1,20 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Data Network Configuration +type DnConfig struct { + // Data Network Name + Dnn string `json:"dnn,omitempty"` + // true: Data network serves local area only false: Data network is not limited to local area + Ladn bool `json:"ladn,omitempty"` + // Edge Compute Service Provider + Ecsp string `json:"ecsp,omitempty"` +} diff --git a/examples/demo9/golang/client/model_domain.go b/examples/demo9/golang/client/model_domain.go new file mode 100644 index 000000000..17370f049 --- /dev/null +++ b/examples/demo9/golang/client/model_domain.go @@ -0,0 +1,35 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Operator domain object +type Domain struct { + // Unique domain ID + Id string `json:"id,omitempty"` + // Domain name + Name string `json:"name,omitempty"` + // Domain type + Type_ string `json:"type,omitempty"` + NetChar *NetworkCharacteristics `json:"netChar,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latency + InterZoneLatency int32 `json:"interZoneLatency,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation + InterZoneLatencyVariation int32 `json:"interZoneLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl + InterZoneThroughput int32 `json:"interZoneThroughput,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss + InterZonePacketLoss float64 `json:"interZonePacketLoss,omitempty"` + // Key/Value Pair Map (string, string) + Meta map[string]string `json:"meta,omitempty"` + // Key/Value Pair Map (string, string) + UserMeta map[string]string `json:"userMeta,omitempty"` + CellularDomainConfig *CellularDomainConfig `json:"cellularDomainConfig,omitempty"` + Zones []Zone `json:"zones,omitempty"` +} diff --git a/examples/demo9/golang/client/model_egress_service.go b/examples/demo9/golang/client/model_egress_service.go new file mode 100644 index 000000000..0d7c98600 --- /dev/null +++ b/examples/demo9/golang/client/model_egress_service.go @@ -0,0 +1,24 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// External service exposed internally via specific port +type EgressService struct { + // Service name + Name string `json:"name,omitempty"` + // Multi-Edge service name, if any + MeSvcName string `json:"meSvcName,omitempty"` + // External node IP address + Ip string `json:"ip,omitempty"` + // Service port number + Port int32 `json:"port,omitempty"` + // Service protocol (TCP or UDP) + Protocol string `json:"protocol,omitempty"` +} diff --git a/examples/demo9/golang/client/model_external_config.go b/examples/demo9/golang/client/model_external_config.go new file mode 100644 index 000000000..ff15ccfb7 --- /dev/null +++ b/examples/demo9/golang/client/model_external_config.go @@ -0,0 +1,16 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// External Process configuration. NOTE: Only valid if 'isExternal' is set. +type ExternalConfig struct { + IngressServiceMap []IngressService `json:"ingressServiceMap,omitempty"` + EgressServiceMap []EgressService `json:"egressServiceMap,omitempty"` +} diff --git a/examples/demo9/golang/client/model_geo_data.go b/examples/demo9/golang/client/model_geo_data.go new file mode 100644 index 000000000..8f25a4a8f --- /dev/null +++ b/examples/demo9/golang/client/model_geo_data.go @@ -0,0 +1,24 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Geographic data +type GeoData struct { + Location *Point `json:"location,omitempty"` + // Optional - Radius (in meters) around the location + Radius float64 `json:"radius,omitempty"` + Path *LineString `json:"path,omitempty"` + // End-of-Path mode:
  • LOOP: When path endpoint is reached, start over from the beginning
  • REVERSE: When path endpoint is reached, return on the reverse path + EopMode string `json:"eopMode,omitempty"` + // Speed of movement along path in m/s + Velocity float64 `json:"velocity,omitempty"` + D2dInRange []string `json:"d2dInRange,omitempty"` + PoaInRange []string `json:"poaInRange,omitempty"` +} diff --git a/examples/demo9/golang/client/model_gpu_config.go b/examples/demo9/golang/client/model_gpu_config.go new file mode 100644 index 000000000..ecc9abc80 --- /dev/null +++ b/examples/demo9/golang/client/model_gpu_config.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// GPU configuration object +type GpuConfig struct { + // Requested GPU type + Type_ string `json:"type,omitempty"` + // Number of GPUs requested + Count int32 `json:"count,omitempty"` +} diff --git a/examples/demo9/golang/client/model_ingress_service.go b/examples/demo9/golang/client/model_ingress_service.go new file mode 100644 index 000000000..b611bccb1 --- /dev/null +++ b/examples/demo9/golang/client/model_ingress_service.go @@ -0,0 +1,22 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Internal service exposed externally via specific port +type IngressService struct { + // Service name (unique or multi-edge) + Name string `json:"name,omitempty"` + // Internal service port number + Port int32 `json:"port,omitempty"` + // Externally-exposed unique service port in range (30000 - 32767) + ExternalPort int32 `json:"externalPort,omitempty"` + // Service protocol (TCP or UDP) + Protocol string `json:"protocol,omitempty"` +} diff --git a/examples/demo9/golang/client/model_line_string.go b/examples/demo9/golang/client/model_line_string.go new file mode 100644 index 000000000..e09207250 --- /dev/null +++ b/examples/demo9/golang/client/model_line_string.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// An array of two or more positions in coordinate space (GeoJSON); a position is an array of two numbers +type LineString struct { + // Must be LineString + Type_ string `json:"type"` + // For a LineString, coordinates is an array of two or more positions; a position is an array of two decimal numbers (longitude and latitude precisely in that order) + Coordinates [][]float64 `json:"coordinates,omitempty"` +} diff --git a/examples/demo9/golang/client/model_memory_config.go b/examples/demo9/golang/client/model_memory_config.go new file mode 100644 index 000000000..67f375533 --- /dev/null +++ b/examples/demo9/golang/client/model_memory_config.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Memory configuration object +type MemoryConfig struct { + // Minimum requested memory + Min int32 `json:"min,omitempty"` + // Maximum requested memory + Max int32 `json:"max,omitempty"` +} diff --git a/examples/demo9/golang/client/model_namespace.go b/examples/demo9/golang/client/model_namespace.go new file mode 100644 index 000000000..8cb160963 --- /dev/null +++ b/examples/demo9/golang/client/model_namespace.go @@ -0,0 +1,16 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + package client + + // Namespace object + type Namespace struct { + // Name of the Sandbox + Sandbox_name string `json:"sandbox_name,omitempty"` + } \ No newline at end of file diff --git a/examples/demo9/golang/client/model_network_characteristics.go b/examples/demo9/golang/client/model_network_characteristics.go new file mode 100644 index 000000000..72a1eb452 --- /dev/null +++ b/examples/demo9/golang/client/model_network_characteristics.go @@ -0,0 +1,28 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Network characteristics object +type NetworkCharacteristics struct { + // Latency in ms + Latency int32 `json:"latency,omitempty"` + // Latency variation in ms + LatencyVariation int32 `json:"latencyVariation,omitempty"` + // Latency distribution. Can only be set in the Scenario Deployment network characteristics, ignored otherwise. Latency distribution is set for the whole network and applied to every end-to-end traffic flows. Default value is 'Normal' distribution. + LatencyDistribution string `json:"latencyDistribution,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by throughputUl and throughputDl + Throughput int32 `json:"throughput,omitempty"` + // Downlink throughput limit in Mbps + ThroughputDl int32 `json:"throughputDl,omitempty"` + // Uplink throughput limit in Mbps + ThroughputUl int32 `json:"throughputUl,omitempty"` + // Packet loss percentage + PacketLoss float64 `json:"packetLoss,omitempty"` +} diff --git a/examples/demo9/golang/client/model_network_location.go b/examples/demo9/golang/client/model_network_location.go new file mode 100644 index 000000000..e6987765f --- /dev/null +++ b/examples/demo9/golang/client/model_network_location.go @@ -0,0 +1,39 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Logical network location object +type NetworkLocation struct { + // Unique network location ID + Id string `json:"id,omitempty"` + // Network location name + Name string `json:"name,omitempty"` + // Network location type + Type_ string `json:"type,omitempty"` + NetChar *NetworkCharacteristics `json:"netChar,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latency + TerminalLinkLatency int32 `json:"terminalLinkLatency,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation + TerminalLinkLatencyVariation int32 `json:"terminalLinkLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl + TerminalLinkThroughput int32 `json:"terminalLinkThroughput,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss + TerminalLinkPacketLoss float64 `json:"terminalLinkPacketLoss,omitempty"` + // Key/Value Pair Map (string, string) + Meta map[string]string `json:"meta,omitempty"` + // Key/Value Pair Map (string, string) + UserMeta map[string]string `json:"userMeta,omitempty"` + CellularPoaConfig *CellularPoaConfig `json:"cellularPoaConfig,omitempty"` + Poa4GConfig *Poa4GConfig `json:"poa4GConfig,omitempty"` + Poa5GConfig *Poa5GConfig `json:"poa5GConfig,omitempty"` + PoaWifiConfig *PoaWifiConfig `json:"poaWifiConfig,omitempty"` + GeoData *GeoData `json:"geoData,omitempty"` + PhysicalLocations []PhysicalLocation `json:"physicalLocations,omitempty"` +} diff --git a/examples/demo9/golang/client/model_oauth.go b/examples/demo9/golang/client/model_oauth.go new file mode 100644 index 000000000..76070524a --- /dev/null +++ b/examples/demo9/golang/client/model_oauth.go @@ -0,0 +1,17 @@ +/* + * MEC Oauth API + * + * The MEC Oauth API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Oauth object +type Oauth struct { + // Oauth + User_code string `json:"user_code,omitempty"` + Verification_uri string `json:"verification_uri,omitempty"` +} diff --git a/examples/demo9/golang/client/model_physical_location.go b/examples/demo9/golang/client/model_physical_location.go new file mode 100644 index 000000000..93ecd86bf --- /dev/null +++ b/examples/demo9/golang/client/model_physical_location.go @@ -0,0 +1,47 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Physical location object +type PhysicalLocation struct { + // Unique physical location ID + Id string `json:"id,omitempty"` + // Physical location name + Name string `json:"name,omitempty"` + // Physical location type + Type_ string `json:"type,omitempty"` + // true: Physical location is external to MEEP false: Physical location is internal to MEEP + IsExternal bool `json:"isExternal,omitempty"` + GeoData *GeoData `json:"geoData,omitempty"` + NetworkLocationsInRange []string `json:"networkLocationsInRange,omitempty"` + // true: Physical location has network connectivity false: Physical location has no network connectivity + Connected bool `json:"connected,omitempty"` + // true: Physical location uses a wireless connection false: Physical location uses a wired connection + Wireless bool `json:"wireless,omitempty"` + // Prioritized, comma-separated list of supported wireless connection types. Default priority if not specififed is 'wifi,5g,4g,other'. Wireless connection types: - 4g - 5g - wifi - other + WirelessType string `json:"wirelessType,omitempty"` + DataNetwork *DnConfig `json:"dataNetwork,omitempty"` + // Key/Value Pair Map (string, string) + Meta map[string]string `json:"meta,omitempty"` + // Key/Value Pair Map (string, string) + UserMeta map[string]string `json:"userMeta,omitempty"` + Processes []Process `json:"processes,omitempty"` + NetChar *NetworkCharacteristics `json:"netChar,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latency + LinkLatency int32 `json:"linkLatency,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation + LinkLatencyVariation int32 `json:"linkLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl + LinkThroughput int32 `json:"linkThroughput,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss + LinkPacketLoss float64 `json:"linkPacketLoss,omitempty"` + // Physical location MAC Address + MacId string `json:"macId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_poa4_g_config.go b/examples/demo9/golang/client/model_poa4_g_config.go new file mode 100644 index 000000000..57656d41d --- /dev/null +++ b/examples/demo9/golang/client/model_poa4_g_config.go @@ -0,0 +1,16 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Cellular 4G POA configuration information +type Poa4GConfig struct { + // The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell + CellId string `json:"cellId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_poa5_g_config.go b/examples/demo9/golang/client/model_poa5_g_config.go new file mode 100644 index 000000000..19fbd1334 --- /dev/null +++ b/examples/demo9/golang/client/model_poa5_g_config.go @@ -0,0 +1,16 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Cellular 5G POA configuration information +type Poa5GConfig struct { + // The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the NR serving the cell + CellId string `json:"cellId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_poa_wifi_config.go b/examples/demo9/golang/client/model_poa_wifi_config.go new file mode 100644 index 000000000..1f20248b7 --- /dev/null +++ b/examples/demo9/golang/client/model_poa_wifi_config.go @@ -0,0 +1,16 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// WIFI POA configuration information +type PoaWifiConfig struct { + // WIFI POA MAC Address + MacId string `json:"macId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_point.go b/examples/demo9/golang/client/model_point.go new file mode 100644 index 000000000..df9b5677e --- /dev/null +++ b/examples/demo9/golang/client/model_point.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// A single position in coordinate space (GeoJSON); a position is an array of two numbers +type Point struct { + // Must be Point + Type_ string `json:"type"` + // For a Point, coordinates MUST be an array of two decimal numbers; longitude and latitude precisely in that order + Coordinates []float64 `json:"coordinates,omitempty"` +} diff --git a/examples/demo9/golang/client/model_problem_details.go b/examples/demo9/golang/client/model_problem_details.go new file mode 100644 index 000000000..b3b825a43 --- /dev/null +++ b/examples/demo9/golang/client/model_problem_details.go @@ -0,0 +1,24 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// The definition of the general \"ProblemDetails\" data structure from IETF RFC 7807 is reproduced inthis structure. Compared to the general framework defined in IETF RFC 7807, the \"status\" and \"detail\" attributes are mandated to be included by the present document, to ensure that the response contains additional textual information about an error. IETF RFC 7807 foresees extensibility of the \"ProblemDetails\" type. It is possible that particular APIs in the present document, or particular implementations, define extensions to define additional attributes that provide more information about the error. The description column only provides some explanation of the meaning to Facilitate understanding of the design. For a full description, see IETF RFC 7807. +type ProblemDetails struct { + // A URI reference according to IETF RFC 3986 that identifies the problem type. It is encouraged that the URI provides human-readable documentation for the problem (e.g. using HTML) when dereferenced. When this member is not present, its value is assumed to be \"about:blank\". + Type_ string `json:"type,omitempty"` + // A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization. If type is given and other than \"about:blank\", this attribute shall also be provided. A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4). + Title string `json:"title,omitempty"` + // The HTTP status code for this occurrence of the problem. The HTTP status code ([RFC7231], Section 6) generated by the origin server 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. It may yield further information if dereferenced. + Instance string `json:"instance,omitempty"` +} diff --git a/examples/demo9/golang/client/model_process.go b/examples/demo9/golang/client/model_process.go new file mode 100644 index 000000000..317b6cd42 --- /dev/null +++ b/examples/demo9/golang/client/model_process.go @@ -0,0 +1,58 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Application or service object +type Process struct { + // Unique process ID + Id string `json:"id,omitempty"` + // Process name + Name string `json:"name,omitempty"` + // Process type + Type_ string `json:"type,omitempty"` + // true: process is external to MEEP false: process is internal to MEEP + IsExternal bool `json:"isExternal,omitempty"` + // Docker image to deploy inside MEEP + Image string `json:"image,omitempty"` + // Environment variables using the format NAME=\"value\",NAME=\"value\",NAME=\"value\" + Environment string `json:"environment,omitempty"` + // Arguments to command executable + CommandArguments string `json:"commandArguments,omitempty"` + // Executable to invoke at container start up + CommandExe string `json:"commandExe,omitempty"` + ServiceConfig *ServiceConfig `json:"serviceConfig,omitempty"` + GpuConfig *GpuConfig `json:"gpuConfig,omitempty"` + MemoryConfig *MemoryConfig `json:"memoryConfig,omitempty"` + CpuConfig *CpuConfig `json:"cpuConfig,omitempty"` + ExternalConfig *ExternalConfig `json:"externalConfig,omitempty"` + // Process status + Status string `json:"status,omitempty"` + // Chart location for the deployment of the chart provided by the user + UserChartLocation string `json:"userChartLocation,omitempty"` + // Chart values.yaml file location for the deployment of the chart provided by the user + UserChartAlternateValues string `json:"userChartAlternateValues,omitempty"` + // Chart supplemental information related to the group (service) + UserChartGroup string `json:"userChartGroup,omitempty"` + // Key/Value Pair Map (string, string) + Meta map[string]string `json:"meta,omitempty"` + // Key/Value Pair Map (string, string) + UserMeta map[string]string `json:"userMeta,omitempty"` + NetChar *NetworkCharacteristics `json:"netChar,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latency + AppLatency int32 `json:"appLatency,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation + AppLatencyVariation int32 `json:"appLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl + AppThroughput int32 `json:"appThroughput,omitempty"` + // **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss + AppPacketLoss float64 `json:"appPacketLoss,omitempty"` + // Identifier used for process placement in AdvantEDGE cluster + PlacementId string `json:"placementId,omitempty"` +} diff --git a/examples/demo9/golang/client/model_sandbox_app_instances.go b/examples/demo9/golang/client/model_sandbox_app_instances.go new file mode 100644 index 000000000..24db2e457 --- /dev/null +++ b/examples/demo9/golang/client/model_sandbox_app_instances.go @@ -0,0 +1,15 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +type SandboxAppInstances struct { + // The application instance identifier. + Id string `json:"id"` +} diff --git a/examples/demo9/golang/client/model_sandbox_logs_subscriptions.go b/examples/demo9/golang/client/model_sandbox_logs_subscriptions.go new file mode 100644 index 000000000..a4e521306 --- /dev/null +++ b/examples/demo9/golang/client/model_sandbox_logs_subscriptions.go @@ -0,0 +1,17 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +type SandboxLogsSubscriptions struct { + // The callback to notify log messages. + CallbackReference string `json:"callbackReference"` + // The reference of the subscription. + SubscriptionReference string `json:"subscriptionReference,omitempty"` +} diff --git a/examples/demo9/golang/client/model_sandbox_mec_services.go b/examples/demo9/golang/client/model_sandbox_mec_services.go new file mode 100644 index 000000000..32dc78ea0 --- /dev/null +++ b/examples/demo9/golang/client/model_sandbox_mec_services.go @@ -0,0 +1,17 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +type SandboxMecServices struct { + // The MEC service name. + Id string `json:"id"` + // When a MEC service is selected, this field contains a token which shall be used in MEC service API URI. + ServiceId string `json:"service_id,omitempty"` +} diff --git a/examples/demo9/golang/client/model_sandbox_network_scenario.go b/examples/demo9/golang/client/model_sandbox_network_scenario.go new file mode 100644 index 000000000..4c0fac6ba --- /dev/null +++ b/examples/demo9/golang/client/model_sandbox_network_scenario.go @@ -0,0 +1,15 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +type SandboxNetworkScenario struct { + // The network scenario name. + Id string `json:"id"` +} diff --git a/examples/demo9/golang/client/model_scenario.go b/examples/demo9/golang/client/model_scenario.go new file mode 100644 index 000000000..913dacfce --- /dev/null +++ b/examples/demo9/golang/client/model_scenario.go @@ -0,0 +1,24 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Scenario object +type Scenario struct { + // Scenario version + Version string `json:"version,omitempty"` + // Unique scenario ID + Id string `json:"id,omitempty"` + // Unique scenario name + Name string `json:"name,omitempty"` + // User description of the scenario. + Description string `json:"description,omitempty"` + Config *ScenarioConfig `json:"config,omitempty"` + Deployment *Deployment `json:"deployment,omitempty"` +} diff --git a/examples/demo9/golang/client/model_scenario_config.go b/examples/demo9/golang/client/model_scenario_config.go new file mode 100644 index 000000000..e23a0529f --- /dev/null +++ b/examples/demo9/golang/client/model_scenario_config.go @@ -0,0 +1,18 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Scenario configuration +type ScenarioConfig struct { + // Visualization configuration + Visualization string `json:"visualization,omitempty"` + // Other scenario configuration + Other string `json:"other,omitempty"` +} diff --git a/examples/demo9/golang/client/model_service_config.go b/examples/demo9/golang/client/model_service_config.go new file mode 100644 index 000000000..b3016e873 --- /dev/null +++ b/examples/demo9/golang/client/model_service_config.go @@ -0,0 +1,19 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Service object +type ServiceConfig struct { + // Unique service name + Name string `json:"name,omitempty"` + // Multi-Edge service name, if any + MeSvcName string `json:"meSvcName,omitempty"` + Ports []ServicePort `json:"ports,omitempty"` +} diff --git a/examples/demo9/golang/client/model_service_port.go b/examples/demo9/golang/client/model_service_port.go new file mode 100644 index 000000000..1b04cf897 --- /dev/null +++ b/examples/demo9/golang/client/model_service_port.go @@ -0,0 +1,20 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Service port object +type ServicePort struct { + // Protocol that the application is using (TCP or UDP) + Protocol string `json:"protocol,omitempty"` + // Port number that the service is listening on + Port int32 `json:"port,omitempty"` + // External port number on which to expose the application (30000 - 32767)
  • Only one application allowed per external port
  • Scenario builder must configure to prevent conflicts + ExternalPort int32 `json:"externalPort,omitempty"` +} diff --git a/examples/demo9/golang/client/model_ue.go b/examples/demo9/golang/client/model_ue.go new file mode 100644 index 000000000..5574dae9b --- /dev/null +++ b/examples/demo9/golang/client/model_ue.go @@ -0,0 +1,17 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +type Ue struct { + // The UE name. + Id string `json:"id"` + // The number of UE instance. + Count int32 `json:"count,omitempty"` +} diff --git a/examples/demo9/golang/client/model_zone.go b/examples/demo9/golang/client/model_zone.go new file mode 100644 index 000000000..fb095e82e --- /dev/null +++ b/examples/demo9/golang/client/model_zone.go @@ -0,0 +1,50 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.9 + * Contact: cti_support@etsi.org + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package client + +// Logical zone (MEC network) object +type Zone struct { + // Unique zone ID + Id string `json:"id,omitempty"` + // Zone name + Name string `json:"name,omitempty"` + // Zone type + Type_ string `json:"type,omitempty"` + NetChar *NetworkCharacteristics `json:"netChar,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterFogLatency int32 `json:"interFogLatency,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterFogLatencyVariation int32 `json:"interFogLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterFogThroughput int32 `json:"interFogThroughput,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterFogPacketLoss float64 `json:"interFogPacketLoss,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterEdgeLatency int32 `json:"interEdgeLatency,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterEdgeLatencyVariation int32 `json:"interEdgeLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterEdgeThroughput int32 `json:"interEdgeThroughput,omitempty"` + // **DEPRECATED** As of release 1.3.0, no longer supported + InterEdgePacketLoss float64 `json:"interEdgePacketLoss,omitempty"` + // **DEPRECATED** As of release 1.3.0, replaced by netChar latency + EdgeFogLatency int32 `json:"edgeFogLatency,omitempty"` + // **DEPRECATED** As of release 1.3.0, replaced by netChar latencyVariation + EdgeFogLatencyVariation int32 `json:"edgeFogLatencyVariation,omitempty"` + // **DEPRECATED** As of release 1.3.0, replaced by netChar throughput + EdgeFogThroughput int32 `json:"edgeFogThroughput,omitempty"` + // **DEPRECATED** As of release 1.3.0, replaced by netChar packetLoss + EdgeFogPacketLoss float64 `json:"edgeFogPacketLoss,omitempty"` + // Key/Value Pair Map (string, string) + Meta map[string]string `json:"meta,omitempty"` + // Key/Value Pair Map (string, string) + UserMeta map[string]string `json:"userMeta,omitempty"` + NetworkLocations []NetworkLocation `json:"networkLocations,omitempty"` +} diff --git a/examples/demo9/golang/client/response.go b/examples/demo9/golang/client/response.go new file mode 100644 index 000000000..13f25177a --- /dev/null +++ b/examples/demo9/golang/client/response.go @@ -0,0 +1,43 @@ +/* + * MEC Sandbox API + * + * The MEC Sandbox API described using OpenAPI + * + * API version: 0.0.2 + * 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 +} diff --git a/examples/demo9/golang/docker_build.sh b/examples/demo9/golang/docker_build.sh new file mode 100755 index 000000000..c93101ee2 --- /dev/null +++ b/examples/demo9/golang/docker_build.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e +set -x + +# Get full path to script directory +SCRIPT=$(readlink -f "$0") +BASEDIR=$(dirname "$SCRIPT") + +DEMOBIN=$BASEDIR/bin/demo9 + +docker pull golang +docker run --rm -it -v$PWD:/opt/local/etsi/demo9 golang bash -c "cd /opt/local/etsi/demo9 && ./build-demo9.sh && chown -R $UID:$UID ./bin" + +echo "" +echo ">>> Demo Service build completed" diff --git a/examples/demo9/golang/docker_run.sh b/examples/demo9/golang/docker_run.sh new file mode 100755 index 000000000..815399607 --- /dev/null +++ b/examples/demo9/golang/docker_run.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e +set +x + +docker pull golang +docker run --rm --expose 80 --expose 443 --publish 80:80 --publish 443:443 -it -v$PWD:/opt/local/etsi/demo9 -v$HOME/var:/opt/local/etsi/var golang bash -c "cd /opt/local/etsi/demo9/bin && ./demo9 ../app_instance.yaml" + +echo "" +echo ">>> Done" diff --git a/examples/demo9/golang/dockerize.sh b/examples/demo9/golang/dockerize.sh new file mode 100755 index 000000000..ca9530a38 --- /dev/null +++ b/examples/demo9/golang/dockerize.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e +set +x + +# Get full path to script directory +SCRIPT=$(readlink -f "$0") +BASEDIR=$(dirname "$SCRIPT") + +DEMOBIN=$BASEDIR/bin + +echo "" +echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +echo ">>> Dockerizing demo9 Server" +echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +echo "" + +# Copy Dockerfile & config to bin folder +cp $BASEDIR/Dockerfile $DEMOBIN +# cp $BASEDIR/src/backend/app_instance.yaml $DEMOBIN +cp $BASEDIR/entrypoint.sh $DEMOBIN + +echo ">>> Dockerizing" +cd $DEMOBIN +docker build --no-cache --rm -t meep-docker-registry:30001/demo9 . +docker push meep-docker-registry:30001/demo9 +cd $BASEDIR + +echo "" +echo ">>> Done" diff --git a/examples/demo9/golang/entrypoint.sh b/examples/demo9/golang/entrypoint.sh new file mode 100755 index 000000000..c17384fc7 --- /dev/null +++ b/examples/demo9/golang/entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +echo "mode: advantedge" >app_instance.yaml +echo "sandbox:" >>app_instance.yaml +echo "mecplatform: ${MEEP_MEP_NAME}" >>app_instance.yaml +echo "appid:" ${MEEP_APP_ID} >>app_instance.yaml +echo "localurl: ${MEEP_POD_NAME}" >>app_instance.yaml +echo "port:" >>app_instance.yaml + +# Start service +exec /demo9 ./app_instance.yaml diff --git a/examples/demo9/golang/git_push.sh b/examples/demo9/golang/git_push.sh new file mode 100644 index 000000000..ae01b182a --- /dev/null +++ b/examples/demo9/golang/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/examples/demo9/golang/go.mod b/examples/demo9/golang/go.mod new file mode 100644 index 000000000..ee71dfdcd --- /dev/null +++ b/examples/demo9/golang/go.mod @@ -0,0 +1,23 @@ +module github.com/InterDigitalInc/AdvantEDGE/example/demo6 + +go 1.18 + +require ( + github.com/google/uuid v1.3.0 + github.com/gorilla/handlers v1.5.1 + github.com/gorilla/mux v1.8.0 + github.com/roymx/viper v1.3.3-0.20190416163942-b9a223fc58a3 + golang.org/x/oauth2 v0.19.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.4.7 // indirect + github.com/magiconair/properties v1.8.0 // indirect + github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/pelletier/go-toml v1.2.0 // indirect + github.com/spf13/cast v1.3.0 // indirect + github.com/spf13/jwalterweatherman v1.0.0 // indirect + github.com/spf13/pflag v1.0.3 // indirect +) diff --git a/examples/demo9/golang/go.sum b/examples/demo9/golang/go.sum new file mode 100644 index 000000000..e8d59f880 --- /dev/null +++ b/examples/demo9/golang/go.sum @@ -0,0 +1,1608 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/InterDigitalInc/AdvantEDGE v1.9.2 h1:CAcF+bn5m0Va2mHFL2lE4awU/kjuF6CjC05phiz8vnk= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= +github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/roymx/viper v1.3.3-0.20190416163942-b9a223fc58a3 h1:lBNvYUFo7d4fHs8BXUmoTzbdUo4usq6PlP5qn894sGA= +github.com/roymx/viper v1.3.3-0.20190416163942-b9a223fc58a3/go.mod h1:jo59Sv6xirZtbxbaZbCtrQd1CSufmcxJZIC8hm2tepw= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= +google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/examples/demo9/golang/main.go b/examples/demo9/golang/main.go new file mode 100644 index 000000000..1367342c5 --- /dev/null +++ b/examples/demo9/golang/main.go @@ -0,0 +1,1993 @@ +/* + * 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. + * + * MEC Demo9 API + * + * Demo9 is a MEC application to illustrate the usage of the MEC Sandbox command line APIs. + * + * API version: 0.0.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package main + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "os" + "os/signal" + "path/filepath" + "regexp" + "strconv" + "strings" + "syscall" + "time" + + client "github.com/InterDigitalInc/AdvantEDGE/example/demo9/client" + + "github.com/google/uuid" + "github.com/gorilla/handlers" + "github.com/roymx/viper" +) + +type Config struct { + Mode string `mapstructure:"mode"` + SandboxUrl string `mapstructure:"sandbox"` + HttpsOnly bool `mapstructure:"https"` + MecPlatform string `mapstructure:"mecplatform"` + SandboxName string `mapstructure:"sandboxname"` + AppInstanceId string `mapstructure:"appid"` + Localurl string `mapstructure:"localurl"` + Port string `mapstructure:"port"` + CallbackUrl string `mapstructure:"callbackUrl"` + CallbackPort string `mapstructure:"callbackPort"` +} + +// MEC 011 registration +// ETSI GS MEC 011 V3.2.1 (2024-04) Clause 7.1.2.6 Type: AppInfo +type AppInfo struct { + AppName string `json:"appName"` // Name of the application. It shall be consistent with the appName in the AppD, if an AppD is available. + AppProvider string `json:"appProvider,omitempty"` // Provider of the application. It shall be consistent with the appProvider in the AppD, if an AppD is available + AppDId string `json:"appDId,omitempty"` // The application descriptor identifier. It is managed by the application provider to identify the application descriptor in a globally unique way + AppInstanceId string `json:"appInstanceId,omitempty"` // Identifier of the application instance. Shall be present if the application instance is instantiated by the MEC Management + IsInsByMec bool `json:"isInsByMec,omitempty"` // Indicate whether the application instance is instantiated by the MEC Management. Default to FALSE if absent. +} + +// MEC 011 ServiceInfo +// ETSI GS MEC 011 V3.2.1 (2024-04) Clause 8.1.2.2 Type: ServiceInfo +type ServiceInfo struct { + SerInstanceId string `json:"serInstanceId,omitempty"` + SerName string `json:"serName"` + SerCategory *CategoryRef `json:"serCategory,omitempty"` + Version string `json:"version"` // Service version + State string `json:"state"` + TransportInfo TransportInfo `json:"transportInfo"` + Serializer string `json:"serializer"` + Links *Links `json:"_links,omitempty"` +} +type CategoryRef struct { + Href string `json:"href"` + Id string `json:"id"` + Name string `json:"name"` + Version string `json:"version"` +} +type TransportInfo struct { + Id string `json:"id"` + Name string `json:"name"` + Type_ *string `json:"type"` + Protocol string `json:"protocol"` + Version string `json:"version"` + SecurityInfo *SecurityInfo `json:"securityInfo"` + Endpoint *OneOfTransportInfoEndpoint `json:"endpoint"` +} +type SecurityInfo struct { + OAuth2Info *SecurityInfoOAuth2Info `json:"oAuth2Info,omitempty"` +} +type SecurityInfoOAuth2Info struct { + GrantTypes []string `json:"grantTypes"` + TokenEndpoint string `json:"tokenEndpoint"` +} +type OneOfTransportInfoEndpoint struct { + EndPointInfoUris + EndPointInfoFqdn + EndPointInfoAddresses + EndPointInfoAlternative +} +type EndPointInfoUris struct { + Uris []string `json:"uris"` +} +type EndPointInfoFqdn struct { + Fqdn []string `json:"fqdn"` +} +type EndPointInfoAddress struct { + Host string `json:"host"` + Port int32 `json:"port"` +} +type EndPointInfoAddresses struct { + Addresses []EndPointInfoAddress `json:"addresses"` +} +type EndPointInfoAlternative struct { + Alternative *interface{} `json:"alternative"` +} + +// MEC 011 Termination subscription +// ETSI GS MEC 011 V3.2.1 (2024-04) Clause 7.1.3.2 Type: AppTerminationNotificationSubscription +type AppTerminationNotificationSubscription struct { + SubscriptionType string `json:"subscriptionType"` + CallbackReference string `json:"callbackReference"` + Links *Self `json:"_links"` + AppInstanceId string `json:"appInstanceId"` +} + +// MEC013 +type UserLocationEventSubscription struct { + Links *Links `json:"_links,omitempty"` + Address string `json:"address,omitempty"` + CallbackReference string `json:"callbackReference,omitempty"` + ClientCorrelator string `json:"clientCorrelator,omitempty"` + ExpiryDeadline *TimeStamp `json:"expiryDeadline,omitempty"` + LocationEventCriteria []string `json:"locationEventCriteria,omitempty"` + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + SubscriptionType string `json:"subscriptionType"` +} + +// MEC 030 V2X Subscription +// ETSI GS MEC 030 V3.2.1 Clause 6.3.5 Type: V2xMsgSubscription +type V2xMsgSubscription struct { + Links *Links `json:"_links,omitempty"` + CallbackReference string `json:"callbackReference,omitempty"` + FilterCriteria *V2xMsgSubscriptionFilterCriteria `json:"filterCriteria"` + RequestTestNotification bool `json:"requestTestNotification,omitempty"` + SubscriptionType string `json:"subscriptionType"` +} + +// MEC 030 V2X Subscription +// ETSI GS MEC 030 V3.2.1 Clause 6.5.15 Type: V2xMsgFilterCriteria +type V2xMsgSubscriptionFilterCriteria struct { + MsgType []string `json:"msgType,omitempty"` + StdOrganization string `json:"stdOrganization"` +} + +type Plmn struct { + Mcc string `json:"mcc"` + Mnc string `json:"mnc"` +} + +type CellId struct { + CellId string `json:"cellId"` +} + +type Ecgi struct { + CellId *CellId `json:"cellId"` + Plmn *Plmn `json:"plmn"` +} + +type LocationInfoGeoArea struct { + Latitude float32 `json:"latitude"` + Longitude float32 `json:"longitude"` +} + +type LocationInfo struct { + Ecgi *Ecgi `json:"ecgi,omitempty"` + GeoArea *LocationInfoGeoArea `json:"geoArea,omitempty"` +} + +type RouteInfo struct { + Location *LocationInfo `json:"location"` + Time *TimeStamp `json:"time,omitempty"` +} + +type Routes struct { + RouteInfo []RouteInfo `json:"routeInfo"` +} + +type PredictionArea struct { + Center *LocationInfo `json:"center"` + Radius string `json:"radius"` +} + +type QosKpi struct { + Confidence string `json:"confidence,omitempty"` + KpiName string `json:"kpiName"` + KpiValue string `json:"kpiValue"` +} + +type Stream struct { + StreamId string `json:"streamId"` + QosKpi []QosKpi `json:"qosKpi"` +} + +type Qos struct { + Stream []Stream `json:"stream"` +} + +type PredictedQos struct { + LocationGranularity string `json:"locationGranularity"` + NoticePeriod *TimeStamp `json:"noticePeriod,omitempty"` + PredictionArea *PredictionArea `json:"predictionArea,omitempty"` + PredictionTarget string `json:"predictionTarget"` + Qos *Qos `json:"qos"` + Routes []Routes `json:"routes,omitempty"` + TimeGranularity *TimeStamp `json:"timeGranularity,omitempty"` +} + +// MEC 040 +type SystemUpdateNotificationSubscription struct { + SubscriptionType string `json:"subscriptionType"` + CallbackReference string `json:"callbackReference"` + Links *Links `json:"links,omitempty"` + SystemId []string `json:"systemId,omitempty"` + ExpiryDeadline *TimeStamp `json:"expiryDeadline,omitempty"` +} + +// MEC Common types +type LinkType struct { + // URI referring to a resource + Href string `json:"href,omitempty"` +} +type Links struct { + Self *LinkType `json:"self"` +} +type Self struct { + Self *LinkType `json:"self"` +} +type TimeStamp struct { + Seconds int32 `json:"seconds"` + NanoSeconds int32 `json:"nanoSeconds"` +} + +type UeContext struct { + id string + v int32 +} + +var ( + dir string + fileName string + provider string = "Jupyter2024" //"github" + run bool = true + done chan bool + cfg *client.Configuration = nil + cl *client.APIClient = nil + reader *bufio.Reader = nil + sandboxName string = "" + verificationUri string = "" + userCode string = "" + mecUrl string = "" + mecPlateform string = "" + callbackUrl string = "" + callbackPort string = "" + terminationSubscriptionID string = "" + scenarios []client.SandboxNetworkScenario + scenario []client.Scenario + scenarioId int + services []client.SandboxMecServices + appsInfo client.ApplicationInfo + isRegistered bool = false + appServiceInfo ServiceInfo + ues []UeContext + subscriptions []LinkType +) + +// Display menu and read selection +const ( + LOGIN = "l" + NAMESPACE = "n" + LOGOUT = "L" + LIST_SC = "s" + SC = "S" + ACTIVATE = "a" + DEACTIVATE = "A" + LIST_SERVICES = "m" + LIST_APP = "M" + CREATE_APP = "c" + DELETE_APP = "C" + MEC011_CONFIRM_READY = "y" + MEC011_REGISTRATION = "r" + MEC011_DEREGISTRATION = "R" + MEC011_CREATE_SVC = "v" + MEC011_DELETE_SVC = "V" + MEC011_GET_SVC = "g" + LIST_UES = "u" + INC_UE = "x" + DEC_UE = "X" + MEC013_UE_LOC = "i" + MEC013_UE_LOC_SUB = "j" + MEC013_UE_LOC_DEL_SUB = "J" + MEC030_UU_SETTINGS = "Y" + MEC030_V2X_SUB = "z" + MEC030_V2X_DEL_SUB = "Z" + MEC030_V2X_QOS = "Q" + MEC040_FED_SYS_GET = "0" + MEC040_FED_SRVS_GET = "1" + MEC040_FED_SRV_GET = "2" + MEC040_FED_SUB_POST = "3" + MEC040_FED_SUB_GET = "4" + MEC040_FED_SUB_DEL = "5" + CAPIF_GET_ALL_SVCS = "10" + CAPIF_GET_SVC = "11" + CAPIF_CREATE_SVC = "12" + CAPIF_DELETE_SVC = "13" + CAPIF_SUB_POST = "14" + CAPIF_SUB_GET = "15" + CAPIF_SUB_DELETE = "16" + STATUS = "T" + QUIT = "q" +) + +func clearScreen() { + fmt.Println("\033[2J") +} + +func menu(message string) []string { + clearScreen() + fmt.Printf( + "Mandatory commands:\n"+ + "\t%s: Login, %s: Logout, %s: Terminate a scenario\n"+ + "Optional commands:\n"+ + "\t%s : Get scenario description\n"+ + "\t%s: Get MEC application services list\n"+ + "\t%s: Get application instances list, %s: Create a new application instance, %s: Delete a new application instance\n"+ + "\t%s: Get UEs, %s : Increase UE, %s : Decrease UE\n"+ + "\t%s: Current status:\n"+ + "MEC 011 App Support:\n"+ + "\t%s: Send ConfirmReady, %s: Send Registration, %s: Send Deregistration\n"+ + "MEC 011 Service Management:\n"+ + "\t%s: Create new service, %s: Delete service, %s: Get list of MEC services\n"+ + "MEC 013:\n"+ + "\t%s : Get UE location, %s : UE location subscription, %s : UE location subscription\n"+ + "MEC 030:\n"+ + "\t%s: Get V2X UU unicast setting, %s: V2X Msg subscription, %s : Delete V2X subscription, %s <[latitudes] [longitudes] [timestamps]: Provide PredictedQoS\n"+ + "\t\t[latitudes] is a set of latitudes separated by comma, [longitudes] is a set of longitudes separated by comma, [timestamps]\n"+ + "\t\tE.g. 43.729416,43.732456 7.414853,7.418417 1653295620,1653299220\n"+ + "MEC 040:\n"+ + "\t%s: Get Federation Systems list, %s : Get Federation Services list, %s : Get Federation Service, %s: Subscribe, %s []: Get subscription, %s : Delete subscription\n"+ + "MEC CAPIF:\n"+ + "\t%s: Get all services, %s: Get service for the current application instance\n"+ + "%s: Quit\n", + LOGIN, NAMESPACE, LOGOUT, LIST_SC, ACTIVATE, DEACTIVATE, SC, LIST_SERVICES, LIST_APP, CREATE_APP, DELETE_APP, LIST_UES, INC_UE, DEC_UE, STATUS, MEC011_CONFIRM_READY, MEC011_REGISTRATION, MEC011_DEREGISTRATION, MEC011_CREATE_SVC, MEC011_DELETE_SVC, MEC011_GET_SVC, MEC013_UE_LOC, MEC013_UE_LOC_SUB, MEC013_UE_LOC_DEL_SUB, MEC030_UU_SETTINGS, MEC030_V2X_SUB, MEC030_V2X_DEL_SUB, MEC030_V2X_QOS, MEC040_FED_SYS_GET, MEC040_FED_SRVS_GET, MEC040_FED_SRV_GET, MEC040_FED_SUB_POST, MEC040_FED_SUB_GET, MEC040_FED_SUB_DEL, CAPIF_GET_ALL_SVCS, CAPIF_GET_SVC, QUIT) + if message != "" { + fmt.Println("Last message: ", message) + } + fmt.Print("Enter your choice: ") + + // Read selection + choice, _ := reader.ReadString('\n') + choice = strings.Trim(strings.Trim(choice, "\n"), " ") + return strings.Split(choice, " ") +} + +func login() (string, string, error) { + fmt.Println(">>> login") + + // Sanity checks + if sandboxName != "" { + return "", "", errors.New("Please, logout first") + } + + // Initialize g;lobal variables + scenarioId = -1 + appsInfo.Id = "" + terminationSubscriptionID = "" + appServiceInfo.SerInstanceId = "" + subscriptions = make([]LinkType, 0) + + sandbox, _, err := cl.AuthorizationApi.Login(context.TODO(), provider) + if err != nil { + return "", "", err + } + fmt.Println("login: sandbox: ", sandbox) + + return sandbox.User_code, sandbox.Verification_uri, nil +} + +func getNamespace() (string, error) { + fmt.Println(">>> Get Namespace") + + response, _, err := cl.AuthorizationApi.GetNamespace(context.TODO(), userCode) + if err != nil { + return "", err + } + fmt.Println("login: Namespace is: ", response) + sandboxName = response.Sandbox_name + + return sandboxName, nil +} + +func logout() error { + fmt.Println(">>> logout: ", sandboxName) + + // Sanity check + if sandboxName == "" { + err := errors.New("logout: Wrong parameters") + return err + } + + // Delete subscriptions done + if len(subscriptions) != 0 { + for _, l := range subscriptions { + delete_subscription(l.Href) + } // End of 'for' statement + } + + // Delete subscription if any + if terminationSubscriptionID != "" { + delete_termination_subscription() + } + + // Delete MEC service if any + if appServiceInfo.SerInstanceId != "" { + mec011_delete_service() + } + + // Delete registration if any + if isRegistered { + mec011_send_deregistration() + } + + // Delete created AppInstId if any + if appsInfo.Id != "" { + deleteMECAppInstId() + appsInfo.Id = "" + time.Sleep(2 * time.Second) + } + + if appServiceInfo.SerInstanceId != "" { + mec011_delete_service() + appServiceInfo.SerInstanceId = "" + time.Sleep(2 * time.Second) + } + + // Terminate scenario if any + if scenarioId != -1 { + terminateScenario(scenarios[scenarioId].Id) + scenarioId = -1 + time.Sleep(2 * time.Second) + } + + _, err := cl.AuthorizationApi.Logout(context.TODO(), sandboxName) + if err != nil { + return err + } + + sandboxName = "" + + return nil +} + +func getListOfScenarios() ([]client.SandboxNetworkScenario, error) { + fmt.Println(">>> getListOfScenarios") + + scenarios, _, err := cl.SandboxNetworkScenariosApi.SandboxNetworkScenariosGET(context.TODO(), sandboxName) + if err != nil { + fmt.Println("getListOfScenarios: ", err.Error()) + return nil, err + } + fmt.Println("getListOfScenarios: ", scenarios) + + return scenarios, nil +} + +func getScenario(scenarioId string) ([]client.Scenario, error) { + fmt.Println(">>> getScenario: ", scenarioId) + + scenario, _, err := cl.SandboxNetworkScenariosApi.SandboxIndividualNetworkScenariosGET(context.TODO(), sandboxName, scenarioId) + if err != nil { + fmt.Println("getScenario: ", err.Error()) + return nil, err + + } + fmt.Println("scenario: ", scenario) + + return scenario, nil +} + +func activateScenario(scenarioId string) error { + fmt.Println(">>> activateScenario: ", scenarioId) + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } + + _, err := cl.SandboxNetworkScenariosApi.SandboxNetworkScenarioPOST(context.TODO(), sandboxName, scenarioId) + if err != nil { + return err + } + + return nil +} + +func terminateScenario(scenarioId string) error { + fmt.Println(">>> terminateScenario: ", scenarioId) + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == "" { + return errors.New("No network scenario available") + } + + _, err := cl.SandboxNetworkScenariosApi.SandboxNetworkScenarioDELETE(context.TODO(), sandboxName, scenarioId) + if err != nil { + return err + } + + return nil +} + +func getListOfMECServices() ([]client.SandboxMecServices, error) { + fmt.Println(">>> getListOfMECServices") + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } + + services, _, err := cl.SandboxMECServicesApi.SandboxMecServicesGET(context.TODO(), sandboxName) + if err != nil { + return nil, err + } + + return services, nil +} + +func getListOfMECAppInstIds() ([]client.ApplicationInfo, error) { + fmt.Println(">>> getListOfMECAppInstIds") + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } + + appsInfos, _, err := cl.SandboxAppInstancesApi.SandboxAppInstancesGET(context.TODO(), sandboxName) + if err != nil { + return nil, err + } + + return appsInfos, nil +} + +func createMECAppInstId(appInfo client.ApplicationInfo) error { + fmt.Println(">>> createMECAppInstId: ", appInfo) + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == -1 { + return errors.New("No network scenario available") + } + + _, _, err := cl.SandboxAppInstancesApi.SandboxAppInstancesPOST(context.TODO(), appInfo, sandboxName) + if err != nil { + return err + } + + return nil +} + +func deleteMECAppInstId() error { + fmt.Println(">>> deleteMECAppInstId") + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == -1 { + return errors.New("No network scenario available") + } + if appsInfo.Id == "" { + return errors.New("No App instance available") + } + + _, err := cl.SandboxAppInstancesApi.SandboxAppInstancesDELETE(context.TODO(), sandboxName, appsInfo.Id) + if err != nil { + return err + } + + return nil +} + +func verify_idx_len(choice string, len int) (int, error) { + idx, err := strconv.Atoi(choice) + if err != nil { + return -1, err + } + if idx >= len { + return -1, errors.New("Index out of range: " + choice) + } + + return idx, nil +} + +func getListOfUes() (ues []UeContext, err error) { + fmt.Println(">>> getListOfUes") + + // Sanity checks + if sandboxName == "" { + return ues, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } + + u, _, err := cl.SandboxUEControllerApi.SandboxUeControllerGET(context.TODO(), sandboxName) + if err != nil { + return ues, err + } + + for _, k := range u { + ues = append(ues, UeContext{id: k.Id, v: k.Count}) + } + fmt.Println("getListOfUes: ues=", ues) + + return ues, nil +} + +func increaseUE(idx int) error { + fmt.Println(">>> increaseUE: idx=", idx) + fmt.Println(">>> increaseUE: ues=", ues[idx]) + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == -1 { + return errors.New("No network scenario available") + } + + if ues[idx].v == 4 { + return errors.New("Already reach the maximum value for " + ues[idx].id) + } + _, err := cl.SandboxUEControllerApi.SandboxUeControllerPATCH(context.TODO(), sandboxName, ues[idx].id, int32(ues[idx].v)) + if err != nil { + return err + } + ues[idx].v = ues[idx].v + 1 + + return nil +} + +func decreaseUE(idx int) error { + fmt.Println(">>> decreaseUE: idx=", idx) + fmt.Println(">>> decreaseUE: ues=", ues[idx]) + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == -1 { + return errors.New("No network scenario available") + } + + if ues[idx].v == 0 { + return errors.New("Already reach the minimum value for " + ues[idx].id) + } + ues[idx].v = ues[idx].v - 1 + _, err := cl.SandboxUEControllerApi.SandboxUeControllerPATCH(context.TODO(), sandboxName, ues[idx].id, int32(ues[idx].v)) + if err != nil { + return err + } + + return nil +} + +func mec011_send_confirm_ready() (subId string, response *http.Response, err error) { + fmt.Println(">>> mec011_send_confirm_ready") + + // Sanity checks + if sandboxName == "" { + return "", nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return "", nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return "", nil, errors.New("No App instance available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_app_support/v2/applications/" + appsInfo.Id + "/confirm_ready" + fmt.Println("mec011_send_confirm_ready: url: " + url) + // Build message body + json_body := "{\"indication\":\"READY\"}" + io_body := strings.NewReader(json_body) + // Send request and await response + _, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return "", nil, err + } + fmt.Println("mec011_send_confirm_ready: confirm ready: " + response.Status) + + return mec011_send_subscribe_termination() +} + +func mec011_send_subscribe_termination() (subId string, response *http.Response, err error) { + fmt.Println(">>> mec011_send_subscribe_termination") + + // Sanity checks + if sandboxName == "" { + return "", nil, errors.New("No sandbox available") + } else if appsInfo.Id == "" { + return "", nil, errors.New("No App instance available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_app_support/v2/applications/" + appsInfo.Id + "/subscriptions" + fmt.Println("mec011_send_subscribe_termination: url: " + url) + // Build message body + appTerminationBody := AppTerminationNotificationSubscription{ + SubscriptionType: "AppTerminationNotificationSubscription", + CallbackReference: callbackUrl + "/asc/termination", + AppInstanceId: appsInfo.Id, + } + json_body, err := json.Marshal(appTerminationBody) + if err != nil { + return "", nil, err + } + fmt.Println("mec011_send_subscribe_termination: json_body: " + string(json_body)) + io_body := bytes.NewReader(json_body) + fmt.Println("mec011_send_subscribe_termination: json_body: ", io_body) + // Send request and await response + _, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return "", nil, err + } + fmt.Println("mec011_send_subscribe_termination: response: " + response.Status) + fmt.Println("mec011_send_subscribe_termination: Location: " + response.Header["Location"][0]) + + subId, err = extract_subscription_id(url, response.Header["Location"][0]) + if err != nil { + return "", nil, err + } + + return subId, response, nil +} + +func delete_termination_subscription() (err error) { + fmt.Println(">>> delete_termination_subscription") + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == -1 { + return errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return errors.New("No App instance available") + } else if terminationSubscriptionID == "" { + return errors.New("No termination subscription") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_app_support/v2/applications/" + appsInfo.Id + "/subscriptions/" + terminationSubscriptionID + fmt.Println("delete_termination_subscription: url: " + url) + // Send request and await response + _, _, err = send_mec_service_request(http.MethodDelete, url, nil, nil, nil, nil) + if err != nil { + fmt.Println("delete_termination_subscription: " + err.Error()) + return err + } + + terminationSubscriptionID = "" + + return nil +} + +func mec011_send_registration() (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec011_send_registration: ", appsInfo.Name) + fmt.Println(">>> mec011_send_registration: ", appsInfo.Id) + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, nil, errors.New("No App instance available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_app_support/v2/registrations" + fmt.Println("mec011_send_registration: url: " + url) + // Build message body + appInfo := AppInfo{ + AppName: appsInfo.Name, + AppProvider: "ETSI", + AppDId: uuid.New().String(), + AppInstanceId: appsInfo.Id, + IsInsByMec: true, + } + fmt.Println("mec011_send_registration: appInfo: ", appInfo) + json_body, err := json.Marshal(appInfo) + if err != nil { + return nil, nil, err + } + fmt.Println("mec011_send_registration: json_body: " + string(json_body)) + io_body := bytes.NewReader(json_body) + fmt.Println("mec011_send_registration: io_body: ", io_body) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + fmt.Println("mec011_send_registration: status: " + response.Status) + fmt.Println("mec011_send_registration: Location: ", response.Header["Location"][0]) + isRegistered = true + + return body, response, nil +} + +func mec011_send_deregistration() (response *http.Response, err error) { + fmt.Println(">>> mec011_send_deregistration") + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, errors.New("No App instance available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_app_support/v2/registrations/" + appsInfo.Id + fmt.Println("mec011_send_deregistration: url: " + url) + // Send request and await response + _, response, err = send_mec_service_request(http.MethodDelete, url, nil, nil, nil, nil) + if err != nil { + return nil, err + } + fmt.Println("mec011_send_deregistration: status: " + response.Status) + + isRegistered = false + + return response, nil +} + +func mec011_create_service() (resId string, response *http.Response, err error) { + fmt.Println(">>> mec011_create_service") + + // Sanity checks + if sandboxName == "" { + return "", nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return "", nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return "", nil, errors.New("No App instance available") + } else if appServiceInfo.SerInstanceId != "" { + return "", nil, errors.New("A MEC service is already created") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_service_mgmt/v1/applications/" + appsInfo.Id + "/services" + fmt.Println("mec011_create_service: url: " + url) + // Build message body + transportType := "REST_HTTP" + appServiceInfo = ServiceInfo{ + SerName: "demo9 MEC Service", + SerCategory: &CategoryRef{ + Href: callbackUrl + "/statistic/v1/quantity", + Id: uuid.New().String(), + Name: "Demo", + Version: "1.0.0", + }, + Version: "1.0.0", + State: "ACTIVE", + TransportInfo: TransportInfo{ + Id: uuid.New().String(), + Name: "HTTP REST API", + Type_: &transportType, + Protocol: "HTTP", + Version: "2.0", + SecurityInfo: &SecurityInfo{}, + Endpoint: &OneOfTransportInfoEndpoint{}, + }, + Serializer: "JSON", + } + appServiceInfo.TransportInfo.Endpoint.Uris = append(appServiceInfo.TransportInfo.Endpoint.Uris, callbackUrl+"/statistic/v1/quantity") + json_body, err := json.Marshal(appServiceInfo) + if err != nil { + return "", nil, err + } + fmt.Println("mec011_create_service: json_body: " + string(json_body)) + io_body := bytes.NewReader(json_body) + fmt.Println("mec011_create_service: json_body: ", io_body) + // Send request and await response + body, response, err := send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return "", nil, err + } + defer response.Body.Close() + if response.StatusCode != 201 { + return "", nil, errors.New("Invalid Status: " + response.Status) + } + // Unmarshal the response body + fmt.Println("mec011_create_service: body: " + string(body)) + err = json.Unmarshal([]byte(body), &appServiceInfo) + if err != nil { + return "", nil, err + } + + fmt.Println("mec011_create_service: Location: " + response.Header["Location"][0]) + resId, err = extract_subscription_id(url, response.Header["Location"][0]) + if err != nil { + return "", nil, err + } + + return resId, response, nil +} + +func mec011_delete_service() (err error) { + fmt.Println(">>> mec011_delete_service") + + // Sanity checks + if sandboxName == "" { + return errors.New("No sandbox available") + } else if scenarioId == -1 { + return errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return errors.New("No App instance available") + } else if appServiceInfo.SerInstanceId == "" { + return errors.New("No MEC service created") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_service_mgmt/v1/applications/" + appsInfo.Id + "/services/" + appServiceInfo.SerInstanceId + fmt.Println("mec011_delete_service: url: " + url) + // Send request and await response + _, _, err = send_mec_service_request(http.MethodDelete, url, nil, nil, nil, nil) + if err != nil { + return err + } + + appServiceInfo.SerInstanceId = "" + + return nil +} + +func mec011_get_mec_services() (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec011_get_mec_services") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, nil, errors.New("No App instance available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/mec_service_mgmt/v1/services" + fmt.Println("mec011_get_mec_services: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, nil, nil +} + +func send_mec_service_request(method string, path string, body io.Reader, vars url.Values, queryParams url.Values, location *string) (resbody []byte, res *http.Response, err error) { + fmt.Println(">>> send_mec_service_request: ", appsInfo.Name) + + // Sanity checks + if sandboxName == "" { + err = errors.New("No sandbox available") + return nil, nil, err + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, 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 + var localVarRequest *http.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, nil, err + } + + // Override request host, if applicable + if cfg.Host != "" { + localVarRequest.Host = cfg.Host + } + + headers := http.Header{} + headers.Set("Accept", "application/json") + localVarRequest.Header = headers + + // Add the user agent to the request. + localVarRequest.Header.Add("User-Agent", cfg.UserAgent) + + //fmt.Println("send_mec_service_request: localVarRequest: ", localVarRequest) + + // tr := &http.Transport{ + // TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + // } + // cfg.HTTPClient = &http.Client{Transport: tr} + + res, err = cfg.HTTPClient.Do(localVarRequest) + if err != nil { + return nil, nil, err + } + + resbody, err = ioutil.ReadAll(res.Body) + if err != nil { + return nil, nil, err + } + res.Body.Close() + + return resbody, res, err +} + +func mec013_get_ue_loc(ue_address string) (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec013_get_ue_loc: ", ue_address) + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if ue_address == "" { + return nil, nil, errors.New("Wrong parameters") + } + + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/location/v3/queries/users?address=" + ue_address + fmt.Println("mec013_get_ue_loc: url: " + url) + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, response, nil +} + +func mec013_subscribe_ue_loc(ue_address string) (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec013_subscribe_ue_loc") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if ue_address == "" { + return nil, nil, errors.New("Wrong parameters") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/location/v3/subscriptions/users" + fmt.Println("mec013_subscribe_ue_loc: url: " + url) + // Build message body + var userLocationEventSubscription = UserLocationEventSubscription{ + Address: ue_address, + CallbackReference: callbackUrl + "/location/v3/users_notification", + ClientCorrelator: "12345", + RequestTestNotification: false, + SubscriptionType: "UserLocationEventSubscription", + } + userLocationEventSubscription.LocationEventCriteria = append(userLocationEventSubscription.LocationEventCriteria, "ENTERING_AREA_EVENT") + userLocationEventSubscription.LocationEventCriteria = append(userLocationEventSubscription.LocationEventCriteria, "LEAVING_AREA_EVENT") + var m = map[string]UserLocationEventSubscription{} + m["userLocationEventSubscription"] = userLocationEventSubscription + json_body, err := json.Marshal(m) + if err != nil { + return nil, nil, err + } + io_body := bytes.NewReader(json_body) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + fmt.Println("mec013_subscribe_ue_loc: body: " + string(body)) + var r = map[string]UserLocationEventSubscription{} + err = json.Unmarshal([]byte(body), &r) + if err != nil { + return nil, nil, err + } + if val, ok := r["userLocationEventSubscription"]; ok { + fmt.Println("mec013_subscribe_ue_loc: userLocationEventSubscription: %v", val) + subscriptions = append(subscriptions, *val.Links.Self) + } else { + err = errors.New("Failed to create User location event subscription") + return nil, nil, err + } + + return body, response, nil +} + +func mec013_delete_ue_loc_subscription(choice string) (response *http.Response, err error) { + fmt.Println(">>> mec013_delete_ue_loc_subscription: ", choice) + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } else if choice == "" { + return nil, errors.New("Wrong parameter") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/location/v3/subscriptions/users/" + choice + fmt.Println("mec013_delete_ue_loc_subscription: url: " + url) + // Send request and await response + response, err = delete_subscription(url) + if err != nil { + return nil, err + } + + return response, nil +} + +func mec030_get_v2x_uu_unicast_setting() (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec030_get_v2x_uu_unicast_setting") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/vis/v2/queries/uu_unicast_provisioning_info?location_info=ecgi,268708941961,268711972264" + fmt.Println("mec030_get_v2x_uu_unicast_setting: url: " + url) + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, response, nil +} + +func mec030_subscribe_v2x_messages() (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec030_subscribe_v2x_messages") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/vis/v2/subscriptions" + fmt.Println("mec030_subscribe_v2x_messages: url: " + url) + // Build message body + var v2xMsgSubscription = V2xMsgSubscription{ + CallbackReference: callbackUrl + "/vis/v2/v2x_msg_notification", + FilterCriteria: &V2xMsgSubscriptionFilterCriteria{ + MsgType: []string{"1", "2", "14", "16"}, // CAM, DENM, CPM & VAM + StdOrganization: "ETSI", + }, + SubscriptionType: "V2xMsgSubscription", + } + json_body, err := json.Marshal(v2xMsgSubscription) + if err != nil { + return nil, nil, err + } + io_body := bytes.NewReader(json_body) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + err = json.Unmarshal([]byte(body), &v2xMsgSubscription) + if err != nil { + return nil, nil, err + } + subscriptions = append(subscriptions, *v2xMsgSubscription.Links.Self) + + return body, response, nil +} + +func mec030_delete_v2x_messages_subscription(choice string) (response *http.Response, err error) { + fmt.Println(">>> mec030_delete_v2x_messages_subscription: ", choice) + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } + if choice == "" { + return nil, errors.New("Wrong parameter") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/vis/v2/subscriptions/" + choice + fmt.Println("mec030_delete_v2x_messages_subscription: url: " + url) + // Send request and await response + response, err = delete_subscription(url) + if err != nil { + return nil, err + } + + return response, nil +} + +// https://www.calculatorsoup.com/calculators/conversions/convert-decimal-degrees-to-degrees-minutes-seconds.php +// https://www.latlong.net/degrees-minutes-seconds-to-decimal-degrees +func mec030_predicted_qos(latitudes string, longitudes string, timestamps string) (body []byte, response *http.Response, err error) { + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if latitudes == "" || longitudes == "" || timestamps == "" { + return nil, nil, errors.New("Wrong parameters") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/vis/v2/provide_predicted_qos" + fmt.Println("mec030_predicted_qos: url: " + url) + // Build message body + // 1. Split arguments into slices + lats := strings.Split(latitudes, ",") + longs := strings.Split(longitudes, ",") + ts := strings.Split(timestamps, ",") + if len(lats) != len(longs) || len(ts) != len(lats) || len(ts) != len(longs) { + return nil, nil, errors.New("Wrong lenght in parameters") + } + // 2. Build routes + var routes = Routes{} + for i, _ := range lats { + lat, err := strconv.ParseFloat(lats[i], 32) + if err != nil { + return nil, nil, errors.New("Wrong latitude value: " + lats[i]) + } + long, err := strconv.ParseFloat(longs[i], 32) + if err != nil { + return nil, nil, errors.New("Wrong longitude value: " + longs[i]) + } + sec, err := strconv.Atoi(ts[i]) + if err != nil { + return nil, nil, errors.New("Wrong timestamp value: " + ts[i]) + } + var routeInfo = RouteInfo{ + Location: &LocationInfo{ + GeoArea: &LocationInfoGeoArea{ + Latitude: float32(lat), + Longitude: float32(long), + }, + }, + Time: &TimeStamp{ + NanoSeconds: 0, + Seconds: int32(sec), + }, + } + routes.RouteInfo = append(routes.RouteInfo, routeInfo) + } + // 3. Build PredictedQos + var predictedQos = PredictedQos{ + PredictionTarget: "SINGLE_UE_PREDICTION", + LocationGranularity: "30", + } + predictedQos.Routes = append(predictedQos.Routes, routes) + json_body, err := json.Marshal(predictedQos) + if err != nil { + return nil, nil, err + } + fmt.Println("mec030_predicted_qos: json_body: " + string(json_body)) + io_body := bytes.NewReader(json_body) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return nil, nil, err + } + + return body, response, nil +} + +func mec40_get_systems_list() (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec40_get_systems_list") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/fed_enablement/v1/fed_resources/systems" + fmt.Println("mec40_get_systems_list: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, response, nil +} + +func mec40_get_services_list(choice string) (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec40_get_services_list") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + if choice == "" { + return nil, nil, errors.New("Wrong parameter") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/fed_enablement/v1/fed_resources/systems/" + choice + "/services" + fmt.Println("mec40_get_services_list: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + + return body, response, nil +} + +func mec40_get_service_list(systemId string, serviceId string) (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec40_get_service_list") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + if systemId == "" || serviceId == "" { + return nil, nil, errors.New("Wrong parameter") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/fed_enablement/v1/fed_resources/systems/" + systemId + "/services/" + serviceId + fmt.Println("mec40_get_service_list: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + + return body, response, nil +} + +func mec40_create_subscription() (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec40_create_subscription") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/fed_enablement/v1/subscriptions" + fmt.Println("mec40_create_subscription: url: " + url) + // Build message body + var systemUpdateNotificationSubscription = SystemUpdateNotificationSubscription{ + SubscriptionType: "SystemUpdateNotificationSubscription", + CallbackReference: callbackUrl + "/fed/v1/notification", + } + json_body, err := json.Marshal(systemUpdateNotificationSubscription) + if err != nil { + return nil, nil, err + } + io_body := bytes.NewReader(json_body) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodPost, url, io_body, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + err = json.Unmarshal([]byte(body), &systemUpdateNotificationSubscription) + if err != nil { + return nil, nil, err + } + subscriptions = append(subscriptions, *systemUpdateNotificationSubscription.Links.Self) + + return body, response, nil +} + +func mec40_get_subscriptions(choice []string) (body []byte, response *http.Response, err error) { + fmt.Println(">>> mec40_get_subscriptions: ", choice) + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/fed_enablement/v1/subscriptions" + if len(choice) == 2 { // Individual GET + url = url + "/" + choice[1] + } + fmt.Println("mec40_get_subscriptions: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, response, nil +} + +func mec40_delete_subscriptions(choice string) (response *http.Response, err error) { + fmt.Println(">>> mec40_delete_subscriptions: ", choice) + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } + if choice == "" { + return nil, errors.New("Wrong parameter") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/fed_enablement/v1/subscriptions/" + choice + fmt.Println("mec40_delete_subscriptions: url: " + url) + // Send request and await response + response, err = delete_subscription(url) + if err != nil { + return nil, err + } + + return response, nil +} + +func capif_get_all_svcs() (body []byte, response *http.Response, err error) { + fmt.Println(">>> capif_get_all_svcs") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/service-apis/v1/allServiceAPIs" + fmt.Println("capif_get_all_svcs: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, response, nil +} + +func capif_get_svc() (body []byte, response *http.Response, err error) { + fmt.Println(">>> capif_get_svc") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, nil, errors.New("No appInstanceId available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/published-apis/v1/" + appsInfo.Id + "/service-apis" + fmt.Println("capif_get_svc: url: " + url) + // Send request and await response + body, response, err = send_mec_service_request(http.MethodGet, url, nil, nil, nil, nil) + if err != nil { + return nil, nil, err + } + defer response.Body.Close() + + return body, response, nil +} + +func capif_create_svc() (body []byte, response *http.Response, err error) { + fmt.Println(">>> capif_create_svc") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, nil, errors.New("No network scenario available") + } + + return nil, nil, errors.New("Not implemented") +} + +func capif_delete_svc(choice string) (response *http.Response, err error) { + fmt.Println(">>> capif_delete_svc: ", choice) + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, errors.New("No appInstanceId available") + } + if choice == "" { + return nil, errors.New("Wrong parameter") + } + + return nil, errors.New("Not implemented") +} + +func capif_create_subscription() (body []byte, response *http.Response, err error) { + fmt.Println(">>> capif_create_subscription") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, nil, errors.New("No network scenario available") + } + + // Set URL + url := mecUrl + "/" + sandboxName + "/" + mecPlateform + "/service-apis/v1/" + appsInfo.Id + "/subscriptions" + fmt.Println("capif_create_subscription: url: " + url) + + return nil, nil, errors.New("Not implemented") +} + +func capif_get_subscriptions() (body []byte, response *http.Response, err error) { + fmt.Println(">>> capif_get_subscriptions") + + // Sanity checks + if sandboxName == "" { + return nil, nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, nil, errors.New("No appInstanceId available") + } + + return nil, nil, errors.New("Not implemented") +} + +func capif_delete_subscriptions(choice string) (response *http.Response, err error) { + fmt.Println(">>> capif_delete_subscriptions: ", choice) + + // Sanity checks + if sandboxName == "" { + return nil, errors.New("No sandbox available") + } else if scenarioId == -1 { + return nil, errors.New("No network scenario available") + } else if appsInfo.Id == "" { + return nil, errors.New("No appInstanceId available") + } + if choice == "" { + return nil, errors.New("Wrong parameter") + } + + return nil, errors.New("Not implemented") +} + +func app_status() (resp string) { + resp = "" + if sandboxName != "" { + resp += "Sandbox: " + sandboxName + } + if appsInfo.Id != "" { + resp += ", appsInfo.Id: " + appsInfo.Id + } + if appServiceInfo.SerInstanceId != "" { + resp += ", SerInstanceId: " + appServiceInfo.SerInstanceId + resp += "- uri: " + appServiceInfo.Links.Self.Href + } + if terminationSubscriptionID != "" { + resp += ", Subscription: " + terminationSubscriptionID + } + if isRegistered { + resp += ", Demo9 app registered" + } else { + resp += ", Demo9 app not registered" + } + if len(subscriptions) != 0 { + resp += ", #" + strconv.Itoa(len(subscriptions)) + " subscriptions created" + } else { + resp += ", no subscriptions created" + } + + return resp +} + +func extract_subscription_id(base_url string, subscription_url string) (string, error) { + fmt.Println(">>> extract_subscription_id: base_url: " + base_url) + fmt.Println(">>> extract_subscription_id: subscription_url: " + subscription_url) + + re := regexp.MustCompile(base_url + "/(?P.+)") + if re == nil { + return "", errors.New("Regexp creation failure") + } + matches := re.FindStringSubmatch(subscription_url) + if matches == nil { + return "", errors.New("Matching failure") + } + + return matches[re.SubexpIndex("sub_id")], nil +} + +func delete_subscription(url string) (response *http.Response, err error) { + fmt.Println(">>> delete_subscription: ", url) + + // Send request and await response + _, response, err = send_mec_service_request(http.MethodDelete, url, nil, nil, nil, nil) + if err != nil { + return nil, err + } + + delete_subscription_from_list(url) + + return response, nil +} + +func delete_subscription_from_list(url string) { + fmt.Println(">>> delete_subscription: ", url) + for s, l := range subscriptions { + if l.Href == url { + subscriptions = append(subscriptions[:s], subscriptions[s+1:]...) + break + } + } +} + +func mec013_notification(w http.ResponseWriter, r *http.Request) { + fmt.Println(">>> mec013_notification: ", r) + w.WriteHeader(http.StatusOK) +} + +func v2x_msg_notification(w http.ResponseWriter, r *http.Request) { + fmt.Println(">>> v2x_msg_notification: ", r) + w.WriteHeader(http.StatusOK) +} + +func fed_notification(w http.ResponseWriter, r *http.Request) { + fmt.Println(">>> fed_notification: ", r) + w.WriteHeader(http.StatusOK) +} + +func capif_notification(w http.ResponseWriter, r *http.Request) { + fmt.Println(">>> capif_notification: ", r) + w.WriteHeader(http.StatusOK) +} + +func mec011_service_statistic_get(w http.ResponseWriter, r *http.Request) { + fmt.Println(">>> mec011_service_statistic_get: ", r) + w.WriteHeader(http.StatusOK) +} + +func main() { + if len(os.Args) < 2 { + // no config argument + fmt.Errorf("Missing parameter, require file path to configurations!") + return + } + + // Read configuration file path in command line arugments + configPath := os.Args[1] + dir = strings.TrimSpace(filepath.Dir(configPath)) + fileName = strings.TrimSpace(filepath.Base(configPath)) + fmt.Println("dir: ", dir) + fmt.Println("fileName: ", fileName) + + // Retrieve environmental variable + var config Config + // trim file extension + envName := strings.TrimSuffix(fileName, ".yaml") + fmt.Println("Using config values from ", dir, "/", envName) + config, err := LoadConfig(dir, envName) + if err != nil { + fmt.Errorf(err.Error()) + return + } + // mecUrl is url of the sandbox system + mecUrl = config.SandboxUrl + // Check mecUrl if uses https + if config.HttpsOnly { + if !strings.HasPrefix(mecUrl, "https://") { + mecUrl = "https://" + mecUrl + } + } else if !config.HttpsOnly { + if !strings.HasPrefix(mecUrl, "http://") { + mecUrl = "http://" + mecUrl + } + } else { + fmt.Errorf("Wrong configuration!") + return + } + if strings.HasSuffix(mecUrl, "/") { + mecUrl = strings.TrimSuffix(mecUrl, "/") + } + mecPlateform = config.MecPlatform + fmt.Println("mecUrl: " + mecUrl) + fmt.Println("mecPlateform: " + mecPlateform) + + callbackUrl = config.CallbackUrl + ":" + config.CallbackPort + fmt.Println("callbackUrl: " + callbackUrl) + + cfg = client.NewConfiguration() + if cfg == nil { + fmt.Errorf("Failed to create client configuration!") + return + } + cfg.BasePath = mecUrl + "/sandbox-api/v1" + fmt.Println("cfg.BasePath: " + cfg.BasePath) + cl = client.NewAPIClient(cfg) + if cl == nil { + fmt.Errorf("Failed to create client reference!") + return + } + + go func() { + // Start demo9 server + reader = bufio.NewReader(os.Stdin) + + var message string = "" + for run { + // Display menu and read selection + choice := menu(message) + + // Apply it + fmt.Println("choice: ", choice) + if strings.Compare(choice[0], "q") == 0 { + run = false + break + } else { + message = process_choice(choice) + } + + } // End of 'for' statement + + }() + + // Listen for SIGKILL + go func() { + sigchan := make(chan os.Signal, 10) + signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) + <-sigchan + fmt.Println("Waiting to shut down program !") + run = false + }() + + // Start REST API Server + go func() { + //fmt.Println(">>> Start REST API Server on port : ", config.CallbackPort) + router := NewRouter() + methods := handlers.AllowedMethods([]string{"OPTIONS", "DELETE", "GET", "HEAD", "POST", "PUT"}) + header := handlers.AllowedHeaders([]string{"content-type"}) + fmt.Println(http.ListenAndServe(":"+config.CallbackPort, handlers.CORS(methods, header)(router))) + run = false + fmt.Println("<<< Stop REST API Server") + }() + + // Listen for demo9 error exit program + go func() { + <-done + fmt.Println("Waiting to shut down program !") + run = false + }() + + for { + // Invoke graceful termination upon program kill + if !run { + fmt.Println("Invoking demo9 graceful termination") + if sandboxName != "" { + logout() + } + break + } + time.Sleep(time.Second) + } +} + +func LoadConfig(path string, name string) (config Config, err error) { + viper.SetConfigType("yaml") + viper.AddConfigPath(path) + viper.SetConfigName(name) + viper.AutomaticEnv() + + err = viper.ReadInConfig() + if err != nil { + return config, err + } + + err = viper.Unmarshal(&config) + if err != nil { + return config, err + } + return + +} + +func process_choice(choice []string) string { + + var message string + if strings.Compare(choice[0], LOGIN) == 0 { // Login + Get Namespace + Get scenarios list + Activate a scenario + // Login + userCode, verificationUri, _ = login() + if userCode == "" { + return fmt.Sprintf("Login failed") + } + message = fmt.Sprintf("User Code: %s and Verification URI is %s: ", userCode, verificationUri) + fmt.Println("message: " + message) + // Get namespace + sandbox, err := getNamespace() + if err != nil { + return err.Error() + } + message = fmt.Sprintf("Sandbox ID is: %s", sandbox) + fmt.Println("message: " + message) + // Retrieve the list of the scenarios + scenarios, _ = getListOfScenarios() + message = fmt.Sprintf("scenarios: %s", fmt.Sprint(scenarios)) + fmt.Println("message: " + message) + // Activate the scenario + scenarioId := 2 // 4g-5g-mv-v2x-fed-iot + scenarioId, err = verify_idx_len(choice[1], len(scenarios)) + if err != nil { + return fmt.Sprintf("Invalid index: %s", err.Error()) + } + err = activateScenario(scenarios[scenarioId].Id) + if err != nil { + scenarioId = -1 + scenarios = nil + return err.Error() + } + message = fmt.Sprintf("Scenario %s activated (wait some seconds before the next command)", scenarios[scenarioId].Id) + fmt.Println("message: " + message) + // Wait for MEC pltf instanciated + time.Sleep(time.Duration(10) * time.Second) + if appsInfo.Id != "" { + scenarioId = -1 + scenarios = nil + return fmt.Sprintf("App instance id already created: %s", appsInfo.Id) + } + appsInfo = client.ApplicationInfo{ + Id: uuid.New().String(), + Name: "demo9 test app", + NodeName: mecPlateform, + Type_: "USER", + Persist: false, + } + err = createMECAppInstId(appsInfo) + if err != nil { + scenarioId = -1 + scenarios = nil + appsInfo = client.ApplicationInfo{} + return err.Error() + } + message = fmt.Sprintf("appsInfo: %s created", fmt.Sprint(appsInfo.Id)) + fmt.Println("message: " + message) + // Send mecApp registration + body, _, err := mec011_send_registration() + if err != nil { + scenarioId = -1 + scenarios = nil + appsInfo = client.ApplicationInfo{} + return err.Error() + } + message = fmt.Sprintf("response body: %s", string(body)) + fmt.Println("message: " + message) + // Send mecApp confirm_ready + body, _, err = mec011_send_registration() + if err != nil { + return err.Error() + } + message = fmt.Sprintf("response body: %s", string(body)) + fmt.Println("message: " + message) + } else if strings.Compare(choice[0], LOGOUT) == 0 { + err := logout() + if err != nil { + return err.Error() + } + message = "Sandbox terminated" + } else if strings.Compare(choice[0], DEACTIVATE) == 0 { + err := terminateScenario(scenarios[scenarioId].Id) + if err != nil { + return err.Error() + } + message = fmt.Sprintf("Scenario %s terminated (wait some seconds before the next command)", scenarios[scenarioId].Id) + scenarioId = -1 + } else if strings.Compare(choice[0], DELETE_APP) == 0 { + err := deleteMECAppInstId() + if err != nil { + return err.Error() + } + message = fmt.Sprintf("appsInfo: %s deleted", fmt.Sprint(appsInfo.Id)) + appsInfo.Id = "" + } else if strings.Compare(choice[0], MEC011_DEREGISTRATION) == 0 { + var err error + response, err := mec011_send_deregistration() + if err != nil { + return err.Error() + } + message = fmt.Sprintf("response body: %s", response.Status) + } else if strings.Compare(choice[0], MEC011_CREATE_SVC) == 0 { + var err error + resId, _, err := mec011_create_service() + if err != nil { + return err.Error() + } + message = fmt.Sprintf("response body: resource id: %s", resId) + } else if strings.Compare(choice[0], MEC011_DELETE_SVC) == 0 { + err := mec011_delete_service() + if err != nil { + return err.Error() + } + message = "MEC Service deleted." + } else if strings.Compare(choice[0], MEC011_GET_SVC) == 0 { + body, _, err := mec011_get_mec_services() + if err != nil { + return err.Error() + } + message = fmt.Sprintf("response body: %s", string(body)) + + } else if strings.Compare(choice[0], STATUS) == 0 { + resp := app_status() + message = fmt.Sprintf("Current status: %s", resp) + } else { + message = fmt.Sprintf("Invalid command: %s", choice) + } + + return message +} diff --git a/examples/demo9/golang/routers.go b/examples/demo9/golang/routers.go new file mode 100644 index 000000000..8fb62b030 --- /dev/null +++ b/examples/demo9/golang/routers.go @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 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 Application Mobility API + * + * Application Mobility Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC021 Application Mobility API](http://www.etsi.org/deliver/etsi_gs/MEC/001_099/021/02.02.01_60/gs_MEC021v020201p.pdf)

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

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

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

    **Note**
    AdvantEDGE supports a selected subset of Application Mobility 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 main + +import ( + "fmt" + "net/http" + + "github.com/gorilla/mux" +) + +type HttpRoute struct { + Name string + Method string + Pattern string + HandlerFunc http.HandlerFunc +} + +type HttpRoutes []HttpRoute + +func NewRouter() *mux.Router { + var handler http.Handler + router := mux.NewRouter().StrictSlash(true) + for _, route := range routes { + handler = route.HandlerFunc + router. + Methods(route.Method). + Path(route.Pattern). + Name(route.Name). + Handler(handler) + } + + return router +} + +func Index(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello World!") +} + +var routes = HttpRoutes{ + HttpRoute{ + "Index", + "GET", + "/", + Index, + }, + HttpRoute{ + "mec013_notification", + "POST", + "/location/v3/users_notification", + mec013_notification, + }, + HttpRoute{ + "v2x_msg_notification", + "POST", + "/vis/v2/v2x_msg_notification", + v2x_msg_notification, + }, + HttpRoute{ + "fed_notification", + "POST", + "/fed/v1/notification", + fed_notification, + }, + HttpRoute{ + "capif_notification", + "POST", + "/mec_capif_mgmt/v1/notification", + capif_notification, + }, + HttpRoute{ + "mec011_service_statistic_get", + "GET", + "/statistic/v1/quantity", + mec011_service_statistic_get, + }, +} diff --git a/examples/demo9/golang/run.sh b/examples/demo9/golang/run.sh new file mode 100755 index 000000000..de4868d87 --- /dev/null +++ b/examples/demo9/golang/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e +set +x + +docker run -it --rm --expose 80/tcp meep-docker-registry:30001/demo9 + +echo "" +echo ">>> Done" diff --git a/examples/demo9/python/README.md b/examples/demo9/python/README.md new file mode 100644 index 000000000..5ac574688 --- /dev/null +++ b/examples/demo9/python/README.md @@ -0,0 +1,6 @@ + +docker pull quay.io/jupyter/base-notebook:latest + +cd ~/etsi-mec-sandbox/examples/demo9/python/ && docker run --rm -it -d --expose 31111 -p 31111:31111 -p 9999:8888 -v"$PWD:/home/jovyan/work" quay.io/jupyter/base-notebook:latest + +curl --verbose --request GET http://mec-platform2.etsi.org:31111/sandbox/v1/statistic/v1/quantity --header "Accept: application/json" --data '{"time":20180124,"data1":"[1516752000,11590.6,11616.9,11590.4,11616.9,0.25202387,1516752060,11622.4,11651.7,11622.4,11644.6,1.03977764]"}' diff --git a/examples/demo9/python/mecapp/.gitignore b/examples/demo9/python/mecapp/.gitignore new file mode 100644 index 000000000..a655050c2 --- /dev/null +++ b/examples/demo9/python/mecapp/.gitignore @@ -0,0 +1,64 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.python-version + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/examples/demo9/python/mecapp/.swagger-codegen-ignore b/examples/demo9/python/mecapp/.swagger-codegen-ignore new file mode 100644 index 000000000..c5fa491b4 --- /dev/null +++ b/examples/demo9/python/mecapp/.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/examples/demo9/python/mecapp/.swagger-codegen/VERSION b/examples/demo9/python/mecapp/.swagger-codegen/VERSION new file mode 100644 index 000000000..2e29f51f4 --- /dev/null +++ b/examples/demo9/python/mecapp/.swagger-codegen/VERSION @@ -0,0 +1 @@ +3.0.55 \ No newline at end of file diff --git a/examples/demo9/python/mecapp/.travis.yml b/examples/demo9/python/mecapp/.travis.yml new file mode 100644 index 000000000..dd6c4450a --- /dev/null +++ b/examples/demo9/python/mecapp/.travis.yml @@ -0,0 +1,13 @@ +# ref: https://docs.travis-ci.com/user/languages/python +language: python +python: + - "3.2" + - "3.3" + - "3.4" + - "3.5" + #- "3.5-dev" # 3.5 development branch + #- "nightly" # points to the latest development branch e.g. 3.6-dev +# command to install dependencies +install: "pip install -r requirements.txt" +# command to run tests +script: nosetests diff --git a/examples/demo9/python/mecapp/README.md b/examples/demo9/python/mecapp/README.md new file mode 100644 index 000000000..8ab9f19f4 --- /dev/null +++ b/examples/demo9/python/mecapp/README.md @@ -0,0 +1,143 @@ +# swagger-client +The MEC Sandbox API described using OpenAPI + +This Python package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project: + +- API version: 0.0.7 +- Package version: 1.0.0 +- Build package: io.swagger.codegen.v3.generators.python.PythonClientCodegen + +## Requirements. + +Python 2.7 and 3.4+ + +## Installation & Usage +### pip install + +If the python package is hosted on Github, you can install directly from Github + +```sh +pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git +``` +(you may need to run `pip` with root permission: `sudo pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git`) + +Then import the package: +```python +import swagger_client +``` + +### Setuptools + +Install via [Setuptools](http://pypi.python.org/pypi/setuptools). + +```sh +python setup.py install --user +``` +(or `sudo python setup.py install` to install the package for all users) + +Then import the package: +```python +import swagger_client +``` + +## Getting Started + +Please follow the [installation procedure](#installation--usage) and then run the following: + +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.AuthorizationApi(swagger_client.ApiClient(configuration)) +provider = 'provider_example' # str | Oauth provider + +try: + # Initiate OAuth login procedure and creates a MEC Sandbox instance + api_response = api_instance.login(provider) + pprint(api_response) +except ApiException as e: + print("Exception when calling AuthorizationApi->login: %s\n" % e) + +# create an instance of the API class +api_instance = swagger_client.AuthorizationApi(swagger_client.ApiClient(configuration)) +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Terminates User Session and delete the Sandbox instance + api_instance.logout(sandbox_name) +except ApiException as e: + print("Exception when calling AuthorizationApi->logout: %s\n" % e) +``` + +## Documentation for API Endpoints + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*AuthorizationApi* | [**login**](docs/AuthorizationApi.md#login) | **POST** /login | Initiate OAuth login procedure and creates a MEC Sandbox instance +*AuthorizationApi* | [**logout**](docs/AuthorizationApi.md#logout) | **POST** /logout | Terminates User Session and delete the Sandbox instance +*SandboxAppInstancesApi* | [**sandbox_app_instances_delete**](docs/SandboxAppInstancesApi.md#sandbox_app_instances_delete) | **DELETE** /sandboxAppInstances/{sandbox_name}/{app_instance_id} | Delete an existing application instance +*SandboxAppInstancesApi* | [**sandbox_app_instances_get**](docs/SandboxAppInstancesApi.md#sandbox_app_instances_get) | **GET** /sandboxAppInstances/{sandbox_name} | Get the list of the available application instance identifiers +*SandboxAppInstancesApi* | [**sandbox_app_instances_post**](docs/SandboxAppInstancesApi.md#sandbox_app_instances_post) | **POST** /sandboxAppInstances/{sandbox_name} | Create a new application instance identifier +*SandboxLogsSubscriptionsApi* | [**sandbox_logs_subscriptions_delete**](docs/SandboxLogsSubscriptionsApi.md#sandbox_logs_subscriptions_delete) | **DELETE** /sandboxLogsSubscriptions/{sandbox_name}/{subscription_reference} | Subscription to receive logs from the sandbox +*SandboxLogsSubscriptionsApi* | [**sandbox_logs_subscriptions_post**](docs/SandboxLogsSubscriptionsApi.md#sandbox_logs_subscriptions_post) | **POST** /sandboxLogsSubscriptions/{sandbox_name} | Subscription to receive logs from the sandbox +*SandboxMECServicesApi* | [**sandbox_mec_services_get**](docs/SandboxMECServicesApi.md#sandbox_mec_services_get) | **GET** /sandboxMecServices/{sandbox_name} | Get the list of the available MEC services +*SandboxNetworkScenariosApi* | [**sandbox_individual_network_scenarios_get**](docs/SandboxNetworkScenariosApi.md#sandbox_individual_network_scenarios_get) | **GET** /sandboxNetworkScenarios/{sandbox_name} | Get description of a Network Scenario to be used. +*SandboxNetworkScenariosApi* | [**sandbox_network_scenario_delete**](docs/SandboxNetworkScenariosApi.md#sandbox_network_scenario_delete) | **DELETE** /sandboxNetworkScenarios/{sandbox_name}/{network_scenario_id} | Deactivate the Network Scenario. +*SandboxNetworkScenariosApi* | [**sandbox_network_scenario_post**](docs/SandboxNetworkScenariosApi.md#sandbox_network_scenario_post) | **POST** /sandboxNetworkScenarios/{sandbox_name} | Selects the Network Scenario to be activated. +*SandboxNetworkScenariosApi* | [**sandbox_network_scenarios_get**](docs/SandboxNetworkScenariosApi.md#sandbox_network_scenarios_get) | **GET** /sandboxNetworkScenarios | Get the list of the available network scenarios +*SandboxUEControllerApi* | [**sandbox_ue_controller_get**](docs/SandboxUEControllerApi.md#sandbox_ue_controller_get) | **GET** /sandboxUeController/{sandbox_name} | Get the list of the available UEs (e.g. \"Stationary UE\") +*SandboxUEControllerApi* | [**sandbox_ue_controller_patch**](docs/SandboxUEControllerApi.md#sandbox_ue_controller_patch) | **PATCH** /sandboxUeController/{sandbox_name} | set the new value of the UE + +## Documentation For Models + + - [ApplicationInfo](docs/ApplicationInfo.md) + - [CellularDomainConfig](docs/CellularDomainConfig.md) + - [CellularPoaConfig](docs/CellularPoaConfig.md) + - [ConnectivityConfig](docs/ConnectivityConfig.md) + - [CpuConfig](docs/CpuConfig.md) + - [D2dConfig](docs/D2dConfig.md) + - [DNConfig](docs/DNConfig.md) + - [Deployment](docs/Deployment.md) + - [Domain](docs/Domain.md) + - [EgressService](docs/EgressService.md) + - [ExternalConfig](docs/ExternalConfig.md) + - [GeoData](docs/GeoData.md) + - [GpuConfig](docs/GpuConfig.md) + - [IngressService](docs/IngressService.md) + - [LineString](docs/LineString.md) + - [MemoryConfig](docs/MemoryConfig.md) + - [NetworkCharacteristics](docs/NetworkCharacteristics.md) + - [NetworkLocation](docs/NetworkLocation.md) + - [PhysicalLocation](docs/PhysicalLocation.md) + - [Poa4GConfig](docs/Poa4GConfig.md) + - [Poa5GConfig](docs/Poa5GConfig.md) + - [PoaWifiConfig](docs/PoaWifiConfig.md) + - [Point](docs/Point.md) + - [ProblemDetails](docs/ProblemDetails.md) + - [Process](docs/Process.md) + - [Sandbox](docs/Sandbox.md) + - [SandboxAppInstances](docs/SandboxAppInstances.md) + - [SandboxLogsSubscriptions](docs/SandboxLogsSubscriptions.md) + - [SandboxMecServices](docs/SandboxMecServices.md) + - [SandboxNetworkScenario](docs/SandboxNetworkScenario.md) + - [Scenario](docs/Scenario.md) + - [ScenarioConfig](docs/ScenarioConfig.md) + - [ServiceConfig](docs/ServiceConfig.md) + - [ServicePort](docs/ServicePort.md) + - [UE](docs/UE.md) + - [Zone](docs/Zone.md) + +## Documentation For Authorization + + All endpoints do not require authorization. + + +## Author + +cti_support@etsi.org diff --git a/examples/demo9/python/mecapp/docs/ApplicationInfo.md b/examples/demo9/python/mecapp/docs/ApplicationInfo.md new file mode 100644 index 000000000..cea763beb --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ApplicationInfo.md @@ -0,0 +1,13 @@ +# ApplicationInfo + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | Application Instance UUID | [optional] +**name** | **str** | Application name | +**node_name** | **str** | Name of node where application instance is running | +**type** | **str** | Application Type | [optional] +**persist** | **bool** | Reserved for internal platform usage | [optional] + +[[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/examples/demo9/python/mecapp/docs/AuthorizationApi.md b/examples/demo9/python/mecapp/docs/AuthorizationApi.md new file mode 100644 index 000000000..11d4a7e23 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/AuthorizationApi.md @@ -0,0 +1,104 @@ +# swagger_client.AuthorizationApi + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**login**](AuthorizationApi.md#login) | **POST** /login | Initiate OAuth login procedure and creates a MEC Sandbox instance +[**logout**](AuthorizationApi.md#logout) | **POST** /logout | Terminates User Session and delete the Sandbox instance + +# **login** +> Sandbox login(provider) + +Initiate OAuth login procedure and creates a MEC Sandbox instance + +Initiate OAuth login procedure and creates a MEC Sandbox instance + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.AuthorizationApi() +provider = 'provider_example' # str | Oauth provider + +try: + # Initiate OAuth login procedure and creates a MEC Sandbox instance + api_response = api_instance.login(provider) + pprint(api_response) +except ApiException as e: + print("Exception when calling AuthorizationApi->login: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **provider** | **str**| Oauth provider | + +### Return type + +[**Sandbox**](Sandbox.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **logout** +> logout(sandbox_name) + +Terminates User Session and delete the Sandbox instance + +Terminates User Session and delete the Sandbox instance + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.AuthorizationApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Terminates User Session and delete the Sandbox instance + api_instance.logout(sandbox_name) +except ApiException as e: + print("Exception when calling AuthorizationApi->logout: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +void (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) + diff --git a/examples/demo9/python/mecapp/docs/CellularDomainConfig.md b/examples/demo9/python/mecapp/docs/CellularDomainConfig.md new file mode 100644 index 000000000..c16f44d63 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/CellularDomainConfig.md @@ -0,0 +1,11 @@ +# CellularDomainConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**mnc** | **str** | Mobile Network Code part of PLMN identity as defined in ETSI TS 136 413 | [optional] +**mcc** | **str** | Mobile Country Code part of PLMN identity as defined in ETSI TS 136 413 | [optional] +**default_cell_id** | **str** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 if no cellId is defined for the cell or if not applicable | [optional] + +[[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/examples/demo9/python/mecapp/docs/CellularPoaConfig.md b/examples/demo9/python/mecapp/docs/CellularPoaConfig.md new file mode 100644 index 000000000..58fa27169 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/CellularPoaConfig.md @@ -0,0 +1,9 @@ +# CellularPoaConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**cell_id** | **str** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell | [optional] + +[[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/examples/demo9/python/mecapp/docs/ConnectivityConfig.md b/examples/demo9/python/mecapp/docs/ConnectivityConfig.md new file mode 100644 index 000000000..e031e425d --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ConnectivityConfig.md @@ -0,0 +1,9 @@ +# ConnectivityConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**model** | **str** | Connectivity Model: <li>OPEN: Any node in the scenario can communicate with any node <li>PDU: Terminal nodes (UE) require a PDU session to the target DN | [optional] + +[[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/examples/demo9/python/mecapp/docs/CpuConfig.md b/examples/demo9/python/mecapp/docs/CpuConfig.md new file mode 100644 index 000000000..ea62fa32f --- /dev/null +++ b/examples/demo9/python/mecapp/docs/CpuConfig.md @@ -0,0 +1,10 @@ +# CpuConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**min** | **float** | Minimum requested CPU | [optional] +**max** | **float** | Maximum requested CPU | [optional] + +[[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/examples/demo9/python/mecapp/docs/D2dConfig.md b/examples/demo9/python/mecapp/docs/D2dConfig.md new file mode 100644 index 000000000..0cc7ba9e5 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/D2dConfig.md @@ -0,0 +1,10 @@ +# D2dConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**d2d_max_distance** | **float** | Maximum distance for D2D. Default distance is 100m | [optional] +**disable_d2d_via_network** | **bool** | Enable-Disable D2D via network. Default value is false | [optional] + +[[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/examples/demo9/python/mecapp/docs/DNConfig.md b/examples/demo9/python/mecapp/docs/DNConfig.md new file mode 100644 index 000000000..98ad28a1e --- /dev/null +++ b/examples/demo9/python/mecapp/docs/DNConfig.md @@ -0,0 +1,11 @@ +# DNConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**dnn** | **str** | Data Network Name | [optional] +**ladn** | **bool** | true: Data network serves local area only false: Data network is not limited to local area | [optional] +**ecsp** | **str** | Edge Compute Service Provider | [optional] + +[[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/examples/demo9/python/mecapp/docs/Deployment.md b/examples/demo9/python/mecapp/docs/Deployment.md new file mode 100644 index 000000000..126d3ec39 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Deployment.md @@ -0,0 +1,18 @@ +# Deployment + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**net_char** | [**NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] +**connectivity** | [**ConnectivityConfig**](ConnectivityConfig.md) | | [optional] +**d2d** | [**D2dConfig**](D2dConfig.md) | | [optional] +**inter_domain_latency** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] +**inter_domain_latency_variation** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] +**inter_domain_throughput** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] +**inter_domain_packet_loss** | **float** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] +**meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**user_meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**domains** | [**list[Domain]**](Domain.md) | | [optional] + +[[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/examples/demo9/python/mecapp/docs/Domain.md b/examples/demo9/python/mecapp/docs/Domain.md new file mode 100644 index 000000000..3eb748697 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Domain.md @@ -0,0 +1,20 @@ +# Domain + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | Unique domain ID | [optional] +**name** | **str** | Domain name | [optional] +**type** | **str** | Domain type | [optional] +**net_char** | [**NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] +**inter_zone_latency** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] +**inter_zone_latency_variation** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] +**inter_zone_throughput** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] +**inter_zone_packet_loss** | **float** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] +**meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**user_meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**cellular_domain_config** | [**CellularDomainConfig**](CellularDomainConfig.md) | | [optional] +**zones** | [**list[Zone]**](Zone.md) | | [optional] + +[[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/examples/demo9/python/mecapp/docs/EgressService.md b/examples/demo9/python/mecapp/docs/EgressService.md new file mode 100644 index 000000000..3bc6057c0 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/EgressService.md @@ -0,0 +1,13 @@ +# EgressService + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**name** | **str** | Service name | [optional] +**me_svc_name** | **str** | Multi-Edge service name, if any | [optional] +**ip** | **str** | External node IP address | [optional] +**port** | **int** | Service port number | [optional] +**protocol** | **str** | Service protocol (TCP or UDP) | [optional] + +[[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/examples/demo9/python/mecapp/docs/ExternalConfig.md b/examples/demo9/python/mecapp/docs/ExternalConfig.md new file mode 100644 index 000000000..3ca868f0e --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ExternalConfig.md @@ -0,0 +1,10 @@ +# ExternalConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ingress_service_map** | [**list[IngressService]**](IngressService.md) | | [optional] +**egress_service_map** | [**list[EgressService]**](EgressService.md) | | [optional] + +[[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/examples/demo9/python/mecapp/docs/GeoData.md b/examples/demo9/python/mecapp/docs/GeoData.md new file mode 100644 index 000000000..63958903f --- /dev/null +++ b/examples/demo9/python/mecapp/docs/GeoData.md @@ -0,0 +1,15 @@ +# GeoData + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**location** | [**Point**](Point.md) | | [optional] +**radius** | **float** | Optional - Radius (in meters) around the location | [optional] +**path** | [**LineString**](LineString.md) | | [optional] +**eop_mode** | **str** | End-of-Path mode: <li>LOOP: When path endpoint is reached, start over from the beginning <li>REVERSE: When path endpoint is reached, return on the reverse path | [optional] +**velocity** | **float** | Speed of movement along path in m/s | [optional] +**d2d_in_range** | **list[str]** | | [optional] +**poa_in_range** | **list[str]** | | [optional] + +[[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/examples/demo9/python/mecapp/docs/GpuConfig.md b/examples/demo9/python/mecapp/docs/GpuConfig.md new file mode 100644 index 000000000..acd3e6265 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/GpuConfig.md @@ -0,0 +1,10 @@ +# GpuConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | Requested GPU type | [optional] +**count** | **int** | Number of GPUs requested | [optional] + +[[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/examples/demo9/python/mecapp/docs/IngressService.md b/examples/demo9/python/mecapp/docs/IngressService.md new file mode 100644 index 000000000..195a46829 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/IngressService.md @@ -0,0 +1,12 @@ +# IngressService + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**name** | **str** | Service name (unique or multi-edge) | [optional] +**port** | **int** | Internal service port number | [optional] +**external_port** | **int** | Externally-exposed unique service port in range (30000 - 32767) | [optional] +**protocol** | **str** | Service protocol (TCP or UDP) | [optional] + +[[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/examples/demo9/python/mecapp/docs/LineString.md b/examples/demo9/python/mecapp/docs/LineString.md new file mode 100644 index 000000000..493827c01 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/LineString.md @@ -0,0 +1,10 @@ +# LineString + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | Must be LineString | +**coordinates** | **list[list[float]]** | For a LineString, coordinates is an array of two or more positions; a position is an array of two decimal numbers (longitude and latitude precisely in that order) | [optional] + +[[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/examples/demo9/python/mecapp/docs/MemoryConfig.md b/examples/demo9/python/mecapp/docs/MemoryConfig.md new file mode 100644 index 000000000..96af92cd2 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/MemoryConfig.md @@ -0,0 +1,10 @@ +# MemoryConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**min** | **int** | Minimum requested memory | [optional] +**max** | **int** | Maximum requested memory | [optional] + +[[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/examples/demo9/python/mecapp/docs/NetworkCharacteristics.md b/examples/demo9/python/mecapp/docs/NetworkCharacteristics.md new file mode 100644 index 000000000..3ee98d790 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/NetworkCharacteristics.md @@ -0,0 +1,15 @@ +# NetworkCharacteristics + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**latency** | **int** | Latency in ms | [optional] +**latency_variation** | **int** | Latency variation in ms | [optional] +**latency_distribution** | **str** | Latency distribution. Can only be set in the Scenario Deployment network characteristics, ignored otherwise. Latency distribution is set for the whole network and applied to every end-to-end traffic flows. Default value is 'Normal' distribution. | [optional] +**throughput** | **int** | **DEPRECATED** As of release 1.5.0, replaced by throughputUl and throughputDl | [optional] +**throughput_dl** | **int** | Downlink throughput limit in Mbps | [optional] +**throughput_ul** | **int** | Uplink throughput limit in Mbps | [optional] +**packet_loss** | **float** | Packet loss percentage | [optional] + +[[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/examples/demo9/python/mecapp/docs/NetworkLocation.md b/examples/demo9/python/mecapp/docs/NetworkLocation.md new file mode 100644 index 000000000..8cf3f2192 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/NetworkLocation.md @@ -0,0 +1,24 @@ +# NetworkLocation + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | Unique network location ID | [optional] +**name** | **str** | Network location name | [optional] +**type** | **str** | Network location type | [optional] +**net_char** | [**NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] +**terminal_link_latency** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] +**terminal_link_latency_variation** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] +**terminal_link_throughput** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] +**terminal_link_packet_loss** | **float** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] +**meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**user_meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**cellular_poa_config** | [**CellularPoaConfig**](CellularPoaConfig.md) | | [optional] +**poa4_g_config** | [**Poa4GConfig**](Poa4GConfig.md) | | [optional] +**poa5_g_config** | [**Poa5GConfig**](Poa5GConfig.md) | | [optional] +**poa_wifi_config** | [**PoaWifiConfig**](PoaWifiConfig.md) | | [optional] +**geo_data** | [**GeoData**](GeoData.md) | | [optional] +**physical_locations** | [**list[PhysicalLocation]**](PhysicalLocation.md) | | [optional] + +[[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/examples/demo9/python/mecapp/docs/PhysicalLocation.md b/examples/demo9/python/mecapp/docs/PhysicalLocation.md new file mode 100644 index 000000000..96f0f7b4f --- /dev/null +++ b/examples/demo9/python/mecapp/docs/PhysicalLocation.md @@ -0,0 +1,27 @@ +# PhysicalLocation + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | Unique physical location ID | [optional] +**name** | **str** | Physical location name | [optional] +**type** | **str** | Physical location type | [optional] +**is_external** | **bool** | true: Physical location is external to MEEP false: Physical location is internal to MEEP | [optional] +**geo_data** | [**GeoData**](GeoData.md) | | [optional] +**network_locations_in_range** | **list[str]** | | [optional] +**connected** | **bool** | true: Physical location has network connectivity false: Physical location has no network connectivity | [optional] +**wireless** | **bool** | true: Physical location uses a wireless connection false: Physical location uses a wired connection | [optional] +**wireless_type** | **str** | Prioritized, comma-separated list of supported wireless connection types. Default priority if not specififed is 'wifi,5g,4g,other'. Wireless connection types: - 4g - 5g - wifi - other | [optional] +**data_network** | [**DNConfig**](DNConfig.md) | | [optional] +**meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**user_meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**processes** | [**list[Process]**](Process.md) | | [optional] +**net_char** | [**NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] +**link_latency** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] +**link_latency_variation** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] +**link_throughput** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] +**link_packet_loss** | **float** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] +**mac_id** | **str** | Physical location MAC Address | [optional] + +[[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/examples/demo9/python/mecapp/docs/Poa4GConfig.md b/examples/demo9/python/mecapp/docs/Poa4GConfig.md new file mode 100644 index 000000000..4188e23c1 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Poa4GConfig.md @@ -0,0 +1,9 @@ +# Poa4GConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**cell_id** | **str** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell | [optional] + +[[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/examples/demo9/python/mecapp/docs/Poa5GConfig.md b/examples/demo9/python/mecapp/docs/Poa5GConfig.md new file mode 100644 index 000000000..3efdfddbd --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Poa5GConfig.md @@ -0,0 +1,9 @@ +# Poa5GConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**cell_id** | **str** | The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the NR serving the cell | [optional] + +[[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/examples/demo9/python/mecapp/docs/PoaWifiConfig.md b/examples/demo9/python/mecapp/docs/PoaWifiConfig.md new file mode 100644 index 000000000..31b4fa8e8 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/PoaWifiConfig.md @@ -0,0 +1,9 @@ +# PoaWifiConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**mac_id** | **str** | WIFI POA MAC Address | [optional] + +[[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/examples/demo9/python/mecapp/docs/Point.md b/examples/demo9/python/mecapp/docs/Point.md new file mode 100644 index 000000000..6dfae907d --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Point.md @@ -0,0 +1,10 @@ +# Point + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | Must be Point | +**coordinates** | **list[float]** | For a Point, coordinates MUST be an array of two decimal numbers; longitude and latitude precisely in that order | [optional] + +[[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/examples/demo9/python/mecapp/docs/ProblemDetails.md b/examples/demo9/python/mecapp/docs/ProblemDetails.md new file mode 100644 index 000000000..d454ef453 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ProblemDetails.md @@ -0,0 +1,13 @@ +# ProblemDetails + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | A URI reference according to IETF RFC 3986 that identifies the problem type. It is encouraged that the URI provides human-readable documentation for the problem (e.g. using HTML) when dereferenced. When this member is not present, its value is assumed to be \"about:blank\". | [optional] +**title** | **str** | A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization. If type is given and other than \"about:blank\", this attribute shall also be provided. A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4). | [optional] +**status** | **int** | The HTTP status code for this occurrence of the problem. The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. | +**detail** | **str** | A human-readable explanation specific to this occurrence of the problem. | +**instance** | **str** | A URI reference that identifies the specific occurrence of the problem. It may yield further information if dereferenced. | [optional] + +[[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/examples/demo9/python/mecapp/docs/Process.md b/examples/demo9/python/mecapp/docs/Process.md new file mode 100644 index 000000000..30dc93224 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Process.md @@ -0,0 +1,33 @@ +# Process + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | Unique process ID | [optional] +**name** | **str** | Process name | [optional] +**type** | **str** | Process type | [optional] +**is_external** | **bool** | true: process is external to MEEP false: process is internal to MEEP | [optional] +**image** | **str** | Docker image to deploy inside MEEP | [optional] +**environment** | **str** | Environment variables using the format NAME=\"value\",NAME=\"value\",NAME=\"value\" | [optional] +**command_arguments** | **str** | Arguments to command executable | [optional] +**command_exe** | **str** | Executable to invoke at container start up | [optional] +**service_config** | [**ServiceConfig**](ServiceConfig.md) | | [optional] +**gpu_config** | [**GpuConfig**](GpuConfig.md) | | [optional] +**memory_config** | [**MemoryConfig**](MemoryConfig.md) | | [optional] +**cpu_config** | [**CpuConfig**](CpuConfig.md) | | [optional] +**external_config** | [**ExternalConfig**](ExternalConfig.md) | | [optional] +**status** | **str** | Process status | [optional] +**user_chart_location** | **str** | Chart location for the deployment of the chart provided by the user | [optional] +**user_chart_alternate_values** | **str** | Chart values.yaml file location for the deployment of the chart provided by the user | [optional] +**user_chart_group** | **str** | Chart supplemental information related to the group (service) | [optional] +**meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**user_meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**net_char** | [**NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] +**app_latency** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latency | [optional] +**app_latency_variation** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation | [optional] +**app_throughput** | **int** | **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl | [optional] +**app_packet_loss** | **float** | **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss | [optional] +**placement_id** | **str** | Identifier used for process placement in AdvantEDGE cluster | [optional] + +[[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/examples/demo9/python/mecapp/docs/Sandbox.md b/examples/demo9/python/mecapp/docs/Sandbox.md new file mode 100644 index 000000000..78f643a7c --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Sandbox.md @@ -0,0 +1,9 @@ +# Sandbox + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**name** | **str** | Sandbox name | [optional] + +[[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/examples/demo9/python/mecapp/docs/SandboxAppInstances.md b/examples/demo9/python/mecapp/docs/SandboxAppInstances.md new file mode 100644 index 000000000..ff2dd7e66 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxAppInstances.md @@ -0,0 +1,9 @@ +# SandboxAppInstances + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | The application instance identifier. | + +[[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/examples/demo9/python/mecapp/docs/SandboxAppInstancesApi.md b/examples/demo9/python/mecapp/docs/SandboxAppInstancesApi.md new file mode 100644 index 000000000..408c3ecd2 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxAppInstancesApi.md @@ -0,0 +1,157 @@ +# swagger_client.SandboxAppInstancesApi + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**sandbox_app_instances_delete**](SandboxAppInstancesApi.md#sandbox_app_instances_delete) | **DELETE** /sandboxAppInstances/{sandbox_name}/{app_instance_id} | Delete an existing application instance +[**sandbox_app_instances_get**](SandboxAppInstancesApi.md#sandbox_app_instances_get) | **GET** /sandboxAppInstances/{sandbox_name} | Get the list of the available application instance identifiers +[**sandbox_app_instances_post**](SandboxAppInstancesApi.md#sandbox_app_instances_post) | **POST** /sandboxAppInstances/{sandbox_name} | Create a new application instance identifier + +# **sandbox_app_instances_delete** +> sandbox_app_instances_delete(sandbox_name, app_instance_id) + +Delete an existing application instance + +This method removes an existing application instance + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxAppInstancesApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier +app_instance_id = 'app_instance_id_example' # str | It uniquely identifies a MEC application instance identifier + +try: + # Delete an existing application instance + api_instance.sandbox_app_instances_delete(sandbox_name, app_instance_id) +except ApiException as e: + print("Exception when calling SandboxAppInstancesApi->sandbox_app_instances_delete: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + **app_instance_id** | **str**| It uniquely identifies a MEC application instance identifier | + +### Return type + +void (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) + +# **sandbox_app_instances_get** +> list[ApplicationInfo] sandbox_app_instances_get(sandbox_name) + +Get the list of the available application instance identifiers + +This method retrieves the list of the available application instance identifiers + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxAppInstancesApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Get the list of the available application instance identifiers + api_response = api_instance.sandbox_app_instances_get(sandbox_name) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxAppInstancesApi->sandbox_app_instances_get: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +[**list[ApplicationInfo]**](ApplicationInfo.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **sandbox_app_instances_post** +> list[ApplicationInfo] sandbox_app_instances_post(body, sandbox_name) + +Create a new application instance identifier + +This method creates a new application instance + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxAppInstancesApi() +body = swagger_client.ApplicationInfo() # ApplicationInfo | Pet to add to the store +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Create a new application instance identifier + api_response = api_instance.sandbox_app_instances_post(body, sandbox_name) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxAppInstancesApi->sandbox_app_instances_post: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **body** | [**ApplicationInfo**](ApplicationInfo.md)| Pet to add to the store | + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +[**list[ApplicationInfo]**](ApplicationInfo.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) + diff --git a/examples/demo9/python/mecapp/docs/SandboxLogsSubscriptions.md b/examples/demo9/python/mecapp/docs/SandboxLogsSubscriptions.md new file mode 100644 index 000000000..5ac3dc4bf --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxLogsSubscriptions.md @@ -0,0 +1,10 @@ +# SandboxLogsSubscriptions + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**callback_reference** | **str** | The callback to notify log messages. | +**subscription_reference** | **str** | The reference of the subscription. | [optional] + +[[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/examples/demo9/python/mecapp/docs/SandboxLogsSubscriptionsApi.md b/examples/demo9/python/mecapp/docs/SandboxLogsSubscriptionsApi.md new file mode 100644 index 000000000..b19495e52 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxLogsSubscriptionsApi.md @@ -0,0 +1,106 @@ +# swagger_client.SandboxLogsSubscriptionsApi + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**sandbox_logs_subscriptions_delete**](SandboxLogsSubscriptionsApi.md#sandbox_logs_subscriptions_delete) | **DELETE** /sandboxLogsSubscriptions/{sandbox_name}/{subscription_reference} | Subscription to receive logs from the sandbox +[**sandbox_logs_subscriptions_post**](SandboxLogsSubscriptionsApi.md#sandbox_logs_subscriptions_post) | **POST** /sandboxLogsSubscriptions/{sandbox_name} | Subscription to receive logs from the sandbox + +# **sandbox_logs_subscriptions_delete** +> sandbox_logs_subscriptions_delete(sandbox_name, subscription_reference) + +Subscription to receive logs from the sandbox + +This method is used to receive logs from the sandbox. + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxLogsSubscriptionsApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier +subscription_reference = 'subscription_reference_example' # str | It uniquely identifies subscription reference to receive logs from the sandbox + +try: + # Subscription to receive logs from the sandbox + api_instance.sandbox_logs_subscriptions_delete(sandbox_name, subscription_reference) +except ApiException as e: + print("Exception when calling SandboxLogsSubscriptionsApi->sandbox_logs_subscriptions_delete: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + **subscription_reference** | **str**| It uniquely identifies subscription reference to receive logs from the sandbox | + +### Return type + +void (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) + +# **sandbox_logs_subscriptions_post** +> list[SandboxLogsSubscriptions] sandbox_logs_subscriptions_post(sandbox_name) + +Subscription to receive logs from the sandbox + +This method is used to receive logs from the sandbox. + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxLogsSubscriptionsApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Subscription to receive logs from the sandbox + api_response = api_instance.sandbox_logs_subscriptions_post(sandbox_name) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxLogsSubscriptionsApi->sandbox_logs_subscriptions_post: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +[**list[SandboxLogsSubscriptions]**](SandboxLogsSubscriptions.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + diff --git a/examples/demo9/python/mecapp/docs/SandboxMECServicesApi.md b/examples/demo9/python/mecapp/docs/SandboxMECServicesApi.md new file mode 100644 index 000000000..237652537 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxMECServicesApi.md @@ -0,0 +1,56 @@ +# swagger_client.SandboxMECServicesApi + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**sandbox_mec_services_get**](SandboxMECServicesApi.md#sandbox_mec_services_get) | **GET** /sandboxMecServices/{sandbox_name} | Get the list of the available MEC services + +# **sandbox_mec_services_get** +> list[SandboxMecServices] sandbox_mec_services_get(sandbox_name) + +Get the list of the available MEC services + +This method retrieves the list of the available MEC services. + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxMECServicesApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Get the list of the available MEC services + api_response = api_instance.sandbox_mec_services_get(sandbox_name) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxMECServicesApi->sandbox_mec_services_get: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +[**list[SandboxMecServices]**](SandboxMecServices.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + diff --git a/examples/demo9/python/mecapp/docs/SandboxMecServices.md b/examples/demo9/python/mecapp/docs/SandboxMecServices.md new file mode 100644 index 000000000..f9799f154 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxMecServices.md @@ -0,0 +1,10 @@ +# SandboxMecServices + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | The MEC service name. | +**service_id** | **str** | When a MEC service is selected, this field contains a token which shall be used in MEC service API URI. | [optional] + +[[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/examples/demo9/python/mecapp/docs/SandboxNetworkScenario.md b/examples/demo9/python/mecapp/docs/SandboxNetworkScenario.md new file mode 100644 index 000000000..cd395dd14 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxNetworkScenario.md @@ -0,0 +1,9 @@ +# SandboxNetworkScenario + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | The network scenario name. | + +[[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/examples/demo9/python/mecapp/docs/SandboxNetworkScenariosApi.md b/examples/demo9/python/mecapp/docs/SandboxNetworkScenariosApi.md new file mode 100644 index 000000000..9199d8a78 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxNetworkScenariosApi.md @@ -0,0 +1,207 @@ +# swagger_client.SandboxNetworkScenariosApi + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**sandbox_individual_network_scenarios_get**](SandboxNetworkScenariosApi.md#sandbox_individual_network_scenarios_get) | **GET** /sandboxNetworkScenarios/{sandbox_name} | Get description of a Network Scenario to be used. +[**sandbox_network_scenario_delete**](SandboxNetworkScenariosApi.md#sandbox_network_scenario_delete) | **DELETE** /sandboxNetworkScenarios/{sandbox_name}/{network_scenario_id} | Deactivate the Network Scenario. +[**sandbox_network_scenario_post**](SandboxNetworkScenariosApi.md#sandbox_network_scenario_post) | **POST** /sandboxNetworkScenarios/{sandbox_name} | Selects the Network Scenario to be activated. +[**sandbox_network_scenarios_get**](SandboxNetworkScenariosApi.md#sandbox_network_scenarios_get) | **GET** /sandboxNetworkScenarios | Get the list of the available network scenarios + +# **sandbox_individual_network_scenarios_get** +> list[Scenario] sandbox_individual_network_scenarios_get(sandbox_name, network_scenario_id) + +Get description of a Network Scenario to be used. + +This method retrive description of a the network scenario + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxNetworkScenariosApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier +network_scenario_id = 'network_scenario_id_example' # str | Network scenario to retrieve + +try: + # Get description of a Network Scenario to be used. + api_response = api_instance.sandbox_individual_network_scenarios_get(sandbox_name, network_scenario_id) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxNetworkScenariosApi->sandbox_individual_network_scenarios_get: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + **network_scenario_id** | **str**| Network scenario to retrieve | + +### Return type + +[**list[Scenario]**](Scenario.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **sandbox_network_scenario_delete** +> sandbox_network_scenario_delete(sandbox_name, network_scenario_id) + +Deactivate the Network Scenario. + +This method deactivates the network scenario + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxNetworkScenariosApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier +network_scenario_id = 'network_scenario_id_example' # str | Network scenario to be used + +try: + # Deactivate the Network Scenario. + api_instance.sandbox_network_scenario_delete(sandbox_name, network_scenario_id) +except ApiException as e: + print("Exception when calling SandboxNetworkScenariosApi->sandbox_network_scenario_delete: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + **network_scenario_id** | **str**| Network scenario to be used | + +### Return type + +void (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) + +# **sandbox_network_scenario_post** +> sandbox_network_scenario_post(sandbox_name, network_scenario_id) + +Selects the Network Scenario to be activated. + +This method selects the network scenario to be activated. This request initiates the creation of necessary MEC services for specific network scenario + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxNetworkScenariosApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier +network_scenario_id = 'network_scenario_id_example' # str | Network scenario to be used + +try: + # Selects the Network Scenario to be activated. + api_instance.sandbox_network_scenario_post(sandbox_name, network_scenario_id) +except ApiException as e: + print("Exception when calling SandboxNetworkScenariosApi->sandbox_network_scenario_post: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + **network_scenario_id** | **str**| Network scenario to be used | + +### Return type + +void (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) + +# **sandbox_network_scenarios_get** +> list[SandboxNetworkScenario] sandbox_network_scenarios_get(sandbox_name) + +Get the list of the available network scenarios + +This method retrieves the list of the available network scenarios. + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxNetworkScenariosApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Get the list of the available network scenarios + api_response = api_instance.sandbox_network_scenarios_get(sandbox_name) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxNetworkScenariosApi->sandbox_network_scenarios_get: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +[**list[SandboxNetworkScenario]**](SandboxNetworkScenario.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + diff --git a/examples/demo9/python/mecapp/docs/SandboxUEControllerApi.md b/examples/demo9/python/mecapp/docs/SandboxUEControllerApi.md new file mode 100644 index 000000000..672ef6afe --- /dev/null +++ b/examples/demo9/python/mecapp/docs/SandboxUEControllerApi.md @@ -0,0 +1,108 @@ +# swagger_client.SandboxUEControllerApi + +All URIs are relative to *http://localhost/sandbox-api/v1* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**sandbox_ue_controller_get**](SandboxUEControllerApi.md#sandbox_ue_controller_get) | **GET** /sandboxUeController/{sandbox_name} | Get the list of the available UEs (e.g. \"Stationary UE\") +[**sandbox_ue_controller_patch**](SandboxUEControllerApi.md#sandbox_ue_controller_patch) | **PATCH** /sandboxUeController/{sandbox_name} | set the new value of the UE + +# **sandbox_ue_controller_get** +> list[UE] sandbox_ue_controller_get(sandbox_name) + +Get the list of the available UEs (e.g. \"Stationary UE\") + +This method retrieves the list of the available available UEs. + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxUEControllerApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier + +try: + # Get the list of the available UEs (e.g. \"Stationary UE\") + api_response = api_instance.sandbox_ue_controller_get(sandbox_name) + pprint(api_response) +except ApiException as e: + print("Exception when calling SandboxUEControllerApi->sandbox_ue_controller_get: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + +### Return type + +[**list[UE]**](UE.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **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) + +# **sandbox_ue_controller_patch** +> sandbox_ue_controller_patch(sandbox_name, user_equipment_id, user_equipment_value) + +set the new value of the UE + +This method sets the new value of the UE. + +### Example +```python +from __future__ import print_function +import time +import swagger_client +from swagger_client.rest import ApiException +from pprint import pprint + +# create an instance of the API class +api_instance = swagger_client.SandboxUEControllerApi() +sandbox_name = 'sandbox_name_example' # str | Sandbox identifier +user_equipment_id = 'user_equipment_id_example' # str | User equipmenet identifier +user_equipment_value = 56 # int | It uniquely identifies a UE to set the new value + +try: + # set the new value of the UE + api_instance.sandbox_ue_controller_patch(sandbox_name, user_equipment_id, user_equipment_value) +except ApiException as e: + print("Exception when calling SandboxUEControllerApi->sandbox_ue_controller_patch: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **sandbox_name** | **str**| Sandbox identifier | + **user_equipment_id** | **str**| User equipmenet identifier | + **user_equipment_value** | **int**| It uniquely identifies a UE to set the new value | + +### Return type + +void (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) + diff --git a/examples/demo9/python/mecapp/docs/Scenario.md b/examples/demo9/python/mecapp/docs/Scenario.md new file mode 100644 index 000000000..7e20fa4c2 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Scenario.md @@ -0,0 +1,14 @@ +# Scenario + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**version** | **str** | Scenario version | [optional] +**id** | **str** | Unique scenario ID | [optional] +**name** | **str** | Unique scenario name | [optional] +**description** | **str** | User description of the scenario. | [optional] +**config** | [**ScenarioConfig**](ScenarioConfig.md) | | [optional] +**deployment** | [**Deployment**](Deployment.md) | | [optional] + +[[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/examples/demo9/python/mecapp/docs/ScenarioConfig.md b/examples/demo9/python/mecapp/docs/ScenarioConfig.md new file mode 100644 index 000000000..49b5204f0 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ScenarioConfig.md @@ -0,0 +1,10 @@ +# ScenarioConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**visualization** | **str** | Visualization configuration | [optional] +**other** | **str** | Other scenario configuration | [optional] + +[[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/examples/demo9/python/mecapp/docs/ServiceConfig.md b/examples/demo9/python/mecapp/docs/ServiceConfig.md new file mode 100644 index 000000000..46344e74b --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ServiceConfig.md @@ -0,0 +1,11 @@ +# ServiceConfig + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**name** | **str** | Unique service name | [optional] +**me_svc_name** | **str** | Multi-Edge service name, if any | [optional] +**ports** | [**list[ServicePort]**](ServicePort.md) | | [optional] + +[[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/examples/demo9/python/mecapp/docs/ServicePort.md b/examples/demo9/python/mecapp/docs/ServicePort.md new file mode 100644 index 000000000..7ff6cfecd --- /dev/null +++ b/examples/demo9/python/mecapp/docs/ServicePort.md @@ -0,0 +1,11 @@ +# ServicePort + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**protocol** | **str** | Protocol that the application is using (TCP or UDP) | [optional] +**port** | **int** | Port number that the service is listening on | [optional] +**external_port** | **int** | External port number on which to expose the application (30000 - 32767) <li>Only one application allowed per external port <li>Scenario builder must configure to prevent conflicts | [optional] + +[[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/examples/demo9/python/mecapp/docs/UE.md b/examples/demo9/python/mecapp/docs/UE.md new file mode 100644 index 000000000..b8cdef1c0 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/UE.md @@ -0,0 +1,9 @@ +# UE + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | The UE name. | + +[[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/examples/demo9/python/mecapp/docs/Zone.md b/examples/demo9/python/mecapp/docs/Zone.md new file mode 100644 index 000000000..9933c7bc6 --- /dev/null +++ b/examples/demo9/python/mecapp/docs/Zone.md @@ -0,0 +1,27 @@ +# Zone + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | Unique zone ID | [optional] +**name** | **str** | Zone name | [optional] +**type** | **str** | Zone type | [optional] +**net_char** | [**NetworkCharacteristics**](NetworkCharacteristics.md) | | [optional] +**inter_fog_latency** | **int** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_fog_latency_variation** | **int** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_fog_throughput** | **int** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_fog_packet_loss** | **float** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_edge_latency** | **int** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_edge_latency_variation** | **int** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_edge_throughput** | **int** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**inter_edge_packet_loss** | **float** | **DEPRECATED** As of release 1.3.0, no longer supported | [optional] +**edge_fog_latency** | **int** | **DEPRECATED** As of release 1.3.0, replaced by netChar latency | [optional] +**edge_fog_latency_variation** | **int** | **DEPRECATED** As of release 1.3.0, replaced by netChar latencyVariation | [optional] +**edge_fog_throughput** | **int** | **DEPRECATED** As of release 1.3.0, replaced by netChar throughput | [optional] +**edge_fog_packet_loss** | **float** | **DEPRECATED** As of release 1.3.0, replaced by netChar packetLoss | [optional] +**meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**user_meta** | **dict(str, str)** | Key/Value Pair Map (string, string) | [optional] +**network_locations** | [**list[NetworkLocation]**](NetworkLocation.md) | | [optional] + +[[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/examples/demo9/python/mecapp/git_push.sh b/examples/demo9/python/mecapp/git_push.sh new file mode 100644 index 000000000..ae01b182a --- /dev/null +++ b/examples/demo9/python/mecapp/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/examples/demo9/python/mecapp/requirements.txt b/examples/demo9/python/mecapp/requirements.txt new file mode 100644 index 000000000..bafdc0753 --- /dev/null +++ b/examples/demo9/python/mecapp/requirements.txt @@ -0,0 +1,5 @@ +certifi >= 14.05.14 +six >= 1.10 +python_dateutil >= 2.5.3 +setuptools >= 21.0.0 +urllib3 >= 1.15.1 diff --git a/examples/demo9/python/mecapp/setup.py b/examples/demo9/python/mecapp/setup.py new file mode 100644 index 000000000..8702e8b5d --- /dev/null +++ b/examples/demo9/python/mecapp/setup.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from setuptools import setup, find_packages # noqa: H301 + +NAME = "swagger-client" +VERSION = "1.0.0" +# To install the library, run the following +# +# python setup.py install +# +# prerequisite: setuptools +# http://pypi.python.org/pypi/setuptools + +REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] + +setup( + name=NAME, + version=VERSION, + description="MEC Sandbox API", + author_email="cti_support@etsi.org", + url="", + keywords=["Swagger", "MEC Sandbox API"], + install_requires=REQUIRES, + packages=find_packages(), + include_package_data=True, + long_description="""\ + The MEC Sandbox API described using OpenAPI # noqa: E501 + """ +) diff --git a/examples/demo9/python/mecapp/swagger_client/__init__.py b/examples/demo9/python/mecapp/swagger_client/__init__.py new file mode 100644 index 000000000..7814929a1 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/__init__.py @@ -0,0 +1,64 @@ +# coding: utf-8 + +# flake8: noqa + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +# import apis into sdk package +from swagger_client.api.authorization_api import AuthorizationApi +from swagger_client.api.sandbox_app_instances_api import SandboxAppInstancesApi +from swagger_client.api.sandbox_logs_subscriptions_api import SandboxLogsSubscriptionsApi +from swagger_client.api.sandbox_mec_services_api import SandboxMECServicesApi +from swagger_client.api.sandbox_network_scenarios_api import SandboxNetworkScenariosApi +from swagger_client.api.sandbox_ue_controller_api import SandboxUEControllerApi +# import ApiClient +from swagger_client.api_client import ApiClient +from swagger_client.configuration import Configuration +# import models into sdk package +from swagger_client.models.application_info import ApplicationInfo +from swagger_client.models.cellular_domain_config import CellularDomainConfig +from swagger_client.models.cellular_poa_config import CellularPoaConfig +from swagger_client.models.connectivity_config import ConnectivityConfig +from swagger_client.models.cpu_config import CpuConfig +from swagger_client.models.d2d_config import D2dConfig +from swagger_client.models.dn_config import DNConfig +from swagger_client.models.deployment import Deployment +from swagger_client.models.domain import Domain +from swagger_client.models.egress_service import EgressService +from swagger_client.models.external_config import ExternalConfig +from swagger_client.models.geo_data import GeoData +from swagger_client.models.gpu_config import GpuConfig +from swagger_client.models.ingress_service import IngressService +from swagger_client.models.line_string import LineString +from swagger_client.models.memory_config import MemoryConfig +from swagger_client.models.namespace import Namespace +from swagger_client.models.network_characteristics import NetworkCharacteristics +from swagger_client.models.network_location import NetworkLocation +from swagger_client.models.oauth import Oauth +from swagger_client.models.physical_location import PhysicalLocation +from swagger_client.models.poa4_g_config import Poa4GConfig +from swagger_client.models.poa5_g_config import Poa5GConfig +from swagger_client.models.poa_wifi_config import PoaWifiConfig +from swagger_client.models.point import Point +from swagger_client.models.problem_details import ProblemDetails +from swagger_client.models.process import Process +from swagger_client.models.sandbox_app_instances import SandboxAppInstances +from swagger_client.models.sandbox_logs_subscriptions import SandboxLogsSubscriptions +from swagger_client.models.sandbox_mec_services import SandboxMecServices +from swagger_client.models.sandbox_network_scenario import SandboxNetworkScenario +from swagger_client.models.scenario import Scenario +from swagger_client.models.scenario_config import ScenarioConfig +from swagger_client.models.service_config import ServiceConfig +from swagger_client.models.service_port import ServicePort +from swagger_client.models.ue import UE +from swagger_client.models.zone import Zone diff --git a/examples/demo9/python/mecapp/swagger_client/api/__init__.py b/examples/demo9/python/mecapp/swagger_client/api/__init__.py new file mode 100644 index 000000000..669ebe130 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/__init__.py @@ -0,0 +1,11 @@ +from __future__ import absolute_import + +# flake8: noqa + +# import apis into api package +from swagger_client.api.authorization_api import AuthorizationApi +from swagger_client.api.sandbox_app_instances_api import SandboxAppInstancesApi +from swagger_client.api.sandbox_logs_subscriptions_api import SandboxLogsSubscriptionsApi +from swagger_client.api.sandbox_mec_services_api import SandboxMECServicesApi +from swagger_client.api.sandbox_network_scenarios_api import SandboxNetworkScenariosApi +from swagger_client.api.sandbox_ue_controller_api import SandboxUEControllerApi diff --git a/examples/demo9/python/mecapp/swagger_client/api/authorization_api.py b/examples/demo9/python/mecapp/swagger_client/api/authorization_api.py new file mode 100644 index 000000000..f07fedafa --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/authorization_api.py @@ -0,0 +1,314 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from swagger_client.api_client import ApiClient + + +class AuthorizationApi(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client + + def get_namespace(self, user_code, **kwargs): # noqa: E501 + """Get the namespace against the User Code # noqa: E501 + + Get the namespace against the User Code # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.get_namespace(user_code, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str user_code: User Code obtained from the login endpoint (required) + :return: Namespace + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.get_namespace_with_http_info(user_code, **kwargs) # noqa: E501 + else: + (data) = self.get_namespace_with_http_info(user_code, **kwargs) # noqa: E501 + return data + + def get_namespace_with_http_info(self, user_code, **kwargs): # noqa: E501 + """Get the namespace against the User Code # noqa: E501 + + Get the namespace against the User Code # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.get_namespace_with_http_info(user_code, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str user_code: User Code obtained from the login endpoint (required) + :return: Namespace + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['user_code'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method get_namespace" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'user_code' is set + if ('user_code' not in params or + params['user_code'] is None): + raise ValueError("Missing the required parameter `user_code` when calling `get_namespace`") # noqa: E501 + + collection_formats = {} + + path_params = {} + + query_params = [] + if 'user_code' in params: + query_params.append(('user_code', params['user_code'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/namespace', 'GET', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='Namespace', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def login(self, provider, **kwargs): # noqa: E501 + """Initiate OAuth login procedure and creates a MEC Sandbox instance # noqa: E501 + + Initiate OAuth login procedure and creates a MEC Sandbox instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.login(provider, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str provider: Oauth provider (required) + :return: Oauth + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.login_with_http_info(provider, **kwargs) # noqa: E501 + else: + (data) = self.login_with_http_info(provider, **kwargs) # noqa: E501 + return data + + def login_with_http_info(self, provider, **kwargs): # noqa: E501 + """Initiate OAuth login procedure and creates a MEC Sandbox instance # noqa: E501 + + Initiate OAuth login procedure and creates a MEC Sandbox instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.login_with_http_info(provider, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str provider: Oauth provider (required) + :return: Oauth + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['provider'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method login" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'provider' is set + if ('provider' not in params or + params['provider'] is None): + raise ValueError("Missing the required parameter `provider` when calling `login`") # noqa: E501 + + collection_formats = {} + + path_params = {} + + query_params = [] + if 'provider' in params: + query_params.append(('provider', params['provider'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/login', 'POST', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='Oauth', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def logout(self, sandbox_name, **kwargs): # noqa: E501 + """Terminates User Session and delete the Sandbox instance # noqa: E501 + + Terminates User Session and delete the Sandbox instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.logout(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.logout_with_http_info(sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.logout_with_http_info(sandbox_name, **kwargs) # noqa: E501 + return data + + def logout_with_http_info(self, sandbox_name, **kwargs): # noqa: E501 + """Terminates User Session and delete the Sandbox instance # noqa: E501 + + Terminates User Session and delete the Sandbox instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.logout_with_http_info(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method logout" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `logout`") # noqa: E501 + + collection_formats = {} + + path_params = {} + + query_params = [] + if 'sandbox_name' in params: + query_params.append(('sandbox_name', params['sandbox_name'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/logout', 'POST', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type=None, # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) diff --git a/examples/demo9/python/mecapp/swagger_client/api/sandbox_app_instances_api.py b/examples/demo9/python/mecapp/swagger_client/api/sandbox_app_instances_api.py new file mode 100644 index 000000000..898f46320 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/sandbox_app_instances_api.py @@ -0,0 +1,334 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from swagger_client.api_client import ApiClient + + +class SandboxAppInstancesApi(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client + + def sandbox_app_instances_delete(self, sandbox_name, app_instance_id, **kwargs): # noqa: E501 + """Delete an existing application instance # noqa: E501 + + This method removes an existing application instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_app_instances_delete(sandbox_name, app_instance_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str app_instance_id: It uniquely identifies a MEC application instance identifier (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_app_instances_delete_with_http_info(sandbox_name, app_instance_id, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_app_instances_delete_with_http_info(sandbox_name, app_instance_id, **kwargs) # noqa: E501 + return data + + def sandbox_app_instances_delete_with_http_info(self, sandbox_name, app_instance_id, **kwargs): # noqa: E501 + """Delete an existing application instance # noqa: E501 + + This method removes an existing application instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_app_instances_delete_with_http_info(sandbox_name, app_instance_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str app_instance_id: It uniquely identifies a MEC application instance identifier (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name', 'app_instance_id'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_app_instances_delete" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_app_instances_delete`") # noqa: E501 + # verify the required parameter 'app_instance_id' is set + if ('app_instance_id' not in params or + params['app_instance_id'] is None): + raise ValueError("Missing the required parameter `app_instance_id` when calling `sandbox_app_instances_delete`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + if 'app_instance_id' in params: + path_params['app_instance_id'] = params['app_instance_id'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxAppInstances/{sandbox_name}/{app_instance_id}', 'DELETE', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type=None, # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_app_instances_get(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available application instance identifiers # noqa: E501 + + This method retrieves the list of the available application instance identifiers # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_app_instances_get(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxAppInstances] + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_app_instances_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_app_instances_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + return data + + def sandbox_app_instances_get_with_http_info(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available application instance identifiers # noqa: E501 + + This method retrieves the list of the available application instance identifiers # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_app_instances_get_with_http_info(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxAppInstances] + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_app_instances_get" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_app_instances_get`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxAppInstances/{sandbox_name}', 'GET', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='list[SandboxAppInstances]', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_app_instances_post(self, body, sandbox_name, **kwargs): # noqa: E501 + """Create a new application instance identifier # noqa: E501 + + This method creates a new application instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_app_instances_post(body, sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param ApplicationInfo body: The application description (required) + :param str sandbox_name: Sandbox identifier (required) + :return: ApplicationInfo + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_app_instances_post_with_http_info(body, sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_app_instances_post_with_http_info(body, sandbox_name, **kwargs) # noqa: E501 + return data + + def sandbox_app_instances_post_with_http_info(self, body, sandbox_name, **kwargs): # noqa: E501 + """Create a new application instance identifier # noqa: E501 + + This method creates a new application instance # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_app_instances_post_with_http_info(body, sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param ApplicationInfo body: The application description (required) + :param str sandbox_name: Sandbox identifier (required) + :return: ApplicationInfo + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['body', 'sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_app_instances_post" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'body' is set + if ('body' not in params or + params['body'] is None): + raise ValueError("Missing the required parameter `body` when calling `sandbox_app_instances_post`") # noqa: E501 + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_app_instances_post`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # HTTP header `Content-Type` + header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxAppInstances/{sandbox_name}', 'POST', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='ApplicationInfo', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) diff --git a/examples/demo9/python/mecapp/swagger_client/api/sandbox_logs_subscriptions_api.py b/examples/demo9/python/mecapp/swagger_client/api/sandbox_logs_subscriptions_api.py new file mode 100644 index 000000000..4904e2d4d --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/sandbox_logs_subscriptions_api.py @@ -0,0 +1,227 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from swagger_client.api_client import ApiClient + + +class SandboxLogsSubscriptionsApi(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client + + def sandbox_logs_subscriptions_delete(self, sandbox_name, subscription_reference, **kwargs): # noqa: E501 + """Subscription to receive logs from the sandbox # noqa: E501 + + This method is used to receive logs from the sandbox. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_logs_subscriptions_delete(sandbox_name, subscription_reference, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str subscription_reference: It uniquely identifies subscription reference to receive logs from the sandbox (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_logs_subscriptions_delete_with_http_info(sandbox_name, subscription_reference, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_logs_subscriptions_delete_with_http_info(sandbox_name, subscription_reference, **kwargs) # noqa: E501 + return data + + def sandbox_logs_subscriptions_delete_with_http_info(self, sandbox_name, subscription_reference, **kwargs): # noqa: E501 + """Subscription to receive logs from the sandbox # noqa: E501 + + This method is used to receive logs from the sandbox. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_logs_subscriptions_delete_with_http_info(sandbox_name, subscription_reference, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str subscription_reference: It uniquely identifies subscription reference to receive logs from the sandbox (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name', 'subscription_reference'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_logs_subscriptions_delete" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_logs_subscriptions_delete`") # noqa: E501 + # verify the required parameter 'subscription_reference' is set + if ('subscription_reference' not in params or + params['subscription_reference'] is None): + raise ValueError("Missing the required parameter `subscription_reference` when calling `sandbox_logs_subscriptions_delete`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + if 'subscription_reference' in params: + path_params['subscription_reference'] = params['subscription_reference'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxLogsSubscriptions/{sandbox_name}/{subscription_reference}', 'DELETE', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type=None, # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_logs_subscriptions_post(self, sandbox_name, **kwargs): # noqa: E501 + """Subscription to receive logs from the sandbox # noqa: E501 + + This method is used to receive logs from the sandbox. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_logs_subscriptions_post(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxLogsSubscriptions] + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_logs_subscriptions_post_with_http_info(sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_logs_subscriptions_post_with_http_info(sandbox_name, **kwargs) # noqa: E501 + return data + + def sandbox_logs_subscriptions_post_with_http_info(self, sandbox_name, **kwargs): # noqa: E501 + """Subscription to receive logs from the sandbox # noqa: E501 + + This method is used to receive logs from the sandbox. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_logs_subscriptions_post_with_http_info(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxLogsSubscriptions] + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_logs_subscriptions_post" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_logs_subscriptions_post`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxLogsSubscriptions/{sandbox_name}', 'POST', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='list[SandboxLogsSubscriptions]', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) diff --git a/examples/demo9/python/mecapp/swagger_client/api/sandbox_mec_services_api.py b/examples/demo9/python/mecapp/swagger_client/api/sandbox_mec_services_api.py new file mode 100644 index 000000000..8286a37ea --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/sandbox_mec_services_api.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from swagger_client.api_client import ApiClient + + +class SandboxMECServicesApi(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client + + def sandbox_mec_services_get(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available MEC services # noqa: E501 + + This method retrieves the list of the available MEC services. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_mec_services_get(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxMecServices] + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_mec_services_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_mec_services_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + return data + + def sandbox_mec_services_get_with_http_info(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available MEC services # noqa: E501 + + This method retrieves the list of the available MEC services. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_mec_services_get_with_http_info(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxMecServices] + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_mec_services_get" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_mec_services_get`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxMecServices/{sandbox_name}', 'GET', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='list[SandboxMecServices]', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) diff --git a/examples/demo9/python/mecapp/swagger_client/api/sandbox_network_scenarios_api.py b/examples/demo9/python/mecapp/swagger_client/api/sandbox_network_scenarios_api.py new file mode 100644 index 000000000..05dc3d666 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/sandbox_network_scenarios_api.py @@ -0,0 +1,429 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from swagger_client.api_client import ApiClient + + +class SandboxNetworkScenariosApi(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client + + def sandbox_individual_network_scenarios_get(self, sandbox_name, network_scenario_id, **kwargs): # noqa: E501 + """Get description of a Network Scenario to be used. # noqa: E501 + + This method retrive description of a the network scenario # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_individual_network_scenarios_get(sandbox_name, network_scenario_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str network_scenario_id: Network scenario to retrieve (required) + :return: list[Scenario] + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_individual_network_scenarios_get_with_http_info(sandbox_name, network_scenario_id, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_individual_network_scenarios_get_with_http_info(sandbox_name, network_scenario_id, **kwargs) # noqa: E501 + return data + + def sandbox_individual_network_scenarios_get_with_http_info(self, sandbox_name, network_scenario_id, **kwargs): # noqa: E501 + """Get description of a Network Scenario to be used. # noqa: E501 + + This method retrive description of a the network scenario # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_individual_network_scenarios_get_with_http_info(sandbox_name, network_scenario_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str network_scenario_id: Network scenario to retrieve (required) + :return: list[Scenario] + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name', 'network_scenario_id'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_individual_network_scenarios_get" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_individual_network_scenarios_get`") # noqa: E501 + # verify the required parameter 'network_scenario_id' is set + if ('network_scenario_id' not in params or + params['network_scenario_id'] is None): + raise ValueError("Missing the required parameter `network_scenario_id` when calling `sandbox_individual_network_scenarios_get`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + if 'network_scenario_id' in params: + query_params.append(('network_scenario_id', params['network_scenario_id'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxNetworkScenarios/{sandbox_name}', 'GET', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='list[Scenario]', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_network_scenario_delete(self, sandbox_name, network_scenario_id, **kwargs): # noqa: E501 + """Deactivate the Network Scenario. # noqa: E501 + + This method deactivates the network scenario # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_network_scenario_delete(sandbox_name, network_scenario_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str network_scenario_id: Network scenario to be used (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_network_scenario_delete_with_http_info(sandbox_name, network_scenario_id, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_network_scenario_delete_with_http_info(sandbox_name, network_scenario_id, **kwargs) # noqa: E501 + return data + + def sandbox_network_scenario_delete_with_http_info(self, sandbox_name, network_scenario_id, **kwargs): # noqa: E501 + """Deactivate the Network Scenario. # noqa: E501 + + This method deactivates the network scenario # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_network_scenario_delete_with_http_info(sandbox_name, network_scenario_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str network_scenario_id: Network scenario to be used (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name', 'network_scenario_id'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_network_scenario_delete" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_network_scenario_delete`") # noqa: E501 + # verify the required parameter 'network_scenario_id' is set + if ('network_scenario_id' not in params or + params['network_scenario_id'] is None): + raise ValueError("Missing the required parameter `network_scenario_id` when calling `sandbox_network_scenario_delete`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + if 'network_scenario_id' in params: + path_params['network_scenario_id'] = params['network_scenario_id'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxNetworkScenarios/{sandbox_name}/{network_scenario_id}', 'DELETE', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type=None, # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_network_scenario_post(self, sandbox_name, network_scenario_id, **kwargs): # noqa: E501 + """Selects the Network Scenario to be activated. # noqa: E501 + + This method selects the network scenario to be activated. This request initiates the creation of necessary MEC services for specific network scenario # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_network_scenario_post(sandbox_name, network_scenario_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str network_scenario_id: Network scenario to be used (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_network_scenario_post_with_http_info(sandbox_name, network_scenario_id, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_network_scenario_post_with_http_info(sandbox_name, network_scenario_id, **kwargs) # noqa: E501 + return data + + def sandbox_network_scenario_post_with_http_info(self, sandbox_name, network_scenario_id, **kwargs): # noqa: E501 + """Selects the Network Scenario to be activated. # noqa: E501 + + This method selects the network scenario to be activated. This request initiates the creation of necessary MEC services for specific network scenario # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_network_scenario_post_with_http_info(sandbox_name, network_scenario_id, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str network_scenario_id: Network scenario to be used (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name', 'network_scenario_id'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_network_scenario_post" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_network_scenario_post`") # noqa: E501 + # verify the required parameter 'network_scenario_id' is set + if ('network_scenario_id' not in params or + params['network_scenario_id'] is None): + raise ValueError("Missing the required parameter `network_scenario_id` when calling `sandbox_network_scenario_post`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + if 'network_scenario_id' in params: + query_params.append(('network_scenario_id', params['network_scenario_id'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxNetworkScenarios/{sandbox_name}', 'POST', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type=None, # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_network_scenarios_get(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available network scenarios # noqa: E501 + + This method retrieves the list of the available network scenarios. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_network_scenarios_get(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxNetworkScenario] + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_network_scenarios_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_network_scenarios_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + return data + + def sandbox_network_scenarios_get_with_http_info(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available network scenarios # noqa: E501 + + This method retrieves the list of the available network scenarios. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_network_scenarios_get_with_http_info(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[SandboxNetworkScenario] + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_network_scenarios_get" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_network_scenarios_get`") # noqa: E501 + + collection_formats = {} + + path_params = {} + + query_params = [] + if 'sandbox_name' in params: + query_params.append(('sandbox_name', params['sandbox_name'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxNetworkScenarios', 'GET', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='list[SandboxNetworkScenario]', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) diff --git a/examples/demo9/python/mecapp/swagger_client/api/sandbox_ue_controller_api.py b/examples/demo9/python/mecapp/swagger_client/api/sandbox_ue_controller_api.py new file mode 100644 index 000000000..3755640cc --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api/sandbox_ue_controller_api.py @@ -0,0 +1,235 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from swagger_client.api_client import ApiClient + + +class SandboxUEControllerApi(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client + + def sandbox_ue_controller_get(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available UEs (e.g. \"Stationary UE\") # noqa: E501 + + This method retrieves the list of the available available UEs. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_ue_controller_get(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[UE] + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_ue_controller_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_ue_controller_get_with_http_info(sandbox_name, **kwargs) # noqa: E501 + return data + + def sandbox_ue_controller_get_with_http_info(self, sandbox_name, **kwargs): # noqa: E501 + """Get the list of the available UEs (e.g. \"Stationary UE\") # noqa: E501 + + This method retrieves the list of the available available UEs. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_ue_controller_get_with_http_info(sandbox_name, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :return: list[UE] + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_ue_controller_get" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_ue_controller_get`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxUeController/{sandbox_name}', 'GET', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type='list[UE]', # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) + + def sandbox_ue_controller_patch(self, sandbox_name, user_equipment_id, user_equipment_value, **kwargs): # noqa: E501 + """set the new value of the UE # noqa: E501 + + This method sets the new value of the UE. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_ue_controller_patch(sandbox_name, user_equipment_id, user_equipment_value, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str user_equipment_id: User equipmenet identifier (required) + :param int user_equipment_value: It uniquely identifies a UE to set the new value (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.sandbox_ue_controller_patch_with_http_info(sandbox_name, user_equipment_id, user_equipment_value, **kwargs) # noqa: E501 + else: + (data) = self.sandbox_ue_controller_patch_with_http_info(sandbox_name, user_equipment_id, user_equipment_value, **kwargs) # noqa: E501 + return data + + def sandbox_ue_controller_patch_with_http_info(self, sandbox_name, user_equipment_id, user_equipment_value, **kwargs): # noqa: E501 + """set the new value of the UE # noqa: E501 + + This method sets the new value of the UE. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.sandbox_ue_controller_patch_with_http_info(sandbox_name, user_equipment_id, user_equipment_value, async_req=True) + >>> result = thread.get() + + :param async_req bool + :param str sandbox_name: Sandbox identifier (required) + :param str user_equipment_id: User equipmenet identifier (required) + :param int user_equipment_value: It uniquely identifies a UE to set the new value (required) + :return: None + If the method is called asynchronously, + returns the request thread. + """ + + all_params = ['sandbox_name', 'user_equipment_id', 'user_equipment_value'] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method sandbox_ue_controller_patch" % key + ) + params[key] = val + del params['kwargs'] + # verify the required parameter 'sandbox_name' is set + if ('sandbox_name' not in params or + params['sandbox_name'] is None): + raise ValueError("Missing the required parameter `sandbox_name` when calling `sandbox_ue_controller_patch`") # noqa: E501 + # verify the required parameter 'user_equipment_id' is set + if ('user_equipment_id' not in params or + params['user_equipment_id'] is None): + raise ValueError("Missing the required parameter `user_equipment_id` when calling `sandbox_ue_controller_patch`") # noqa: E501 + # verify the required parameter 'user_equipment_value' is set + if ('user_equipment_value' not in params or + params['user_equipment_value'] is None): + raise ValueError("Missing the required parameter `user_equipment_value` when calling `sandbox_ue_controller_patch`") # noqa: E501 + + collection_formats = {} + + path_params = {} + if 'sandbox_name' in params: + path_params['sandbox_name'] = params['sandbox_name'] # noqa: E501 + + query_params = [] + if 'user_equipment_id' in params: + query_params.append(('user_equipment_id', params['user_equipment_id'])) # noqa: E501 + if 'user_equipment_value' in params: + query_params.append(('user_equipment_value', params['user_equipment_value'])) # noqa: E501 + + header_params = {} + + form_params = [] + local_var_files = {} + + body_params = None + # Authentication setting + auth_settings = [] # noqa: E501 + + return self.api_client.call_api( + '/sandboxUeController/{sandbox_name}', 'PATCH', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type=None, # noqa: E501 + auth_settings=auth_settings, + async_req=params.get('async_req'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) diff --git a/examples/demo9/python/mecapp/swagger_client/api_client.py b/examples/demo9/python/mecapp/swagger_client/api_client.py new file mode 100644 index 000000000..a72b51c02 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/api_client.py @@ -0,0 +1,634 @@ +# coding: utf-8 +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" +from __future__ import absolute_import + +import datetime +import json +import mimetypes +from multiprocessing.pool import ThreadPool +import os +import re +import tempfile + +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import quote + +from swagger_client.configuration import Configuration +import swagger_client.models +from swagger_client import rest + + +class ApiClient(object): + """Generic API client for Swagger client library builds. + + Swagger generic API client. This client handles the client- + server communication, and is invariant across implementations. Specifics of + the methods and models for each application are generated from the Swagger + templates. + + NOTE: This class is auto generated by the swagger code generator program. + Ref: https://github.com/swagger-api/swagger-codegen + Do not edit the class manually. + + :param configuration: .Configuration object for this client + :param header_name: a header to pass when making calls to the API. + :param header_value: a header value to pass when making calls to + the API. + :param cookie: a cookie to include in the header when making calls + to the API + """ + + PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types + NATIVE_TYPES_MAPPING = { + 'int': int, + 'long': int if six.PY3 else long, # noqa: F821 + 'float': float, + 'str': str, + 'bool': bool, + 'date': datetime.date, + 'datetime': datetime.datetime, + 'object': object, + } + + def __init__(self, configuration=None, header_name=None, header_value=None, + cookie=None): + if configuration is None: + configuration = Configuration() + self.configuration = configuration + + self.pool = ThreadPool() + self.rest_client = rest.RESTClientObject(configuration) + self.default_headers = {} + if header_name is not None: + self.default_headers[header_name] = header_value + self.cookie = cookie + # Set default User-Agent. + self.user_agent = 'Swagger-Codegen/1.0.0/python' + + def __del__(self): + self.pool.close() + self.pool.join() + + @property + def user_agent(self): + """User agent for this API client""" + return self.default_headers['User-Agent'] + + @user_agent.setter + def user_agent(self, value): + self.default_headers['User-Agent'] = value + + def set_default_header(self, header_name, header_value): + self.default_headers[header_name] = header_value + + def __call_api( + self, resource_path, method, path_params=None, + query_params=None, header_params=None, body=None, post_params=None, + files=None, response_type=None, auth_settings=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None): + + config = self.configuration + + # header parameters + header_params = header_params or {} + header_params.update(self.default_headers) + if self.cookie: + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) + header_params = dict(self.parameters_to_tuples(header_params, + collection_formats)) + + # path parameters + if path_params: + path_params = self.sanitize_for_serialization(path_params) + path_params = self.parameters_to_tuples(path_params, + collection_formats) + for k, v in path_params: + # specified safe chars, encode everything + resource_path = resource_path.replace( + '{%s}' % k, + quote(str(v), safe=config.safe_chars_for_path_param) + ) + + # query parameters + if query_params: + query_params = self.sanitize_for_serialization(query_params) + query_params = self.parameters_to_tuples(query_params, + collection_formats) + + # post parameters + if post_params or files: + post_params = self.prepare_post_parameters(post_params, files) + post_params = self.sanitize_for_serialization(post_params) + post_params = self.parameters_to_tuples(post_params, + collection_formats) + + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + + # body + if body: + body = self.sanitize_for_serialization(body) + + # request url + url = self.configuration.host + resource_path + + # perform request and return response + response_data = self.request( + method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, + _preload_content=_preload_content, + _request_timeout=_request_timeout) + + self.last_response = response_data + + return_data = response_data + if _preload_content: + # deserialize response data + if response_type: + return_data = self.deserialize(response_data, response_type) + else: + #return_data = None + return (return_data, response_data.status, + response_data.getheaders()) # ETSI STF 678 (FSCOM) + + if _return_http_data_only: + return (return_data) + else: + return (return_data, response_data.status, + response_data.getheaders()) + + def sanitize_for_serialization(self, obj): + """Builds a JSON POST object. + + If obj is None, return None. + If obj is str, int, long, float, bool, return directly. + If obj is datetime.datetime, datetime.date + convert to string in iso8601 format. + If obj is list, sanitize each element in the list. + If obj is dict, return the dict. + If obj is swagger model, return the properties dict. + + :param obj: The data to serialize. + :return: The serialized form of data. + """ + if obj is None: + return None + elif isinstance(obj, self.PRIMITIVE_TYPES): + return obj + elif isinstance(obj, list): + return [self.sanitize_for_serialization(sub_obj) + for sub_obj in obj] + elif isinstance(obj, tuple): + return tuple(self.sanitize_for_serialization(sub_obj) + for sub_obj in obj) + elif isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + + if isinstance(obj, dict): + obj_dict = obj + else: + # Convert model obj to dict except + # attributes `swagger_types`, `attribute_map` + # and attributes which value is not None. + # Convert attribute name to json key in + # model definition for request. + obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) + for attr, _ in six.iteritems(obj.swagger_types) + if getattr(obj, attr) is not None} + + return {key: self.sanitize_for_serialization(val) + for key, val in six.iteritems(obj_dict)} + + def deserialize(self, response, response_type): + """Deserializes response into an object. + + :param response: RESTResponse object to be deserialized. + :param response_type: class literal for + deserialized object, or string of class name. + + :return: deserialized object. + """ + # handle file downloading + # save response body into a tmp file and return the instance + if response_type == "file": + return self.__deserialize_file(response) + + # fetch data from response object + try: + data = json.loads(response.data) + except ValueError: + data = response.data + + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if type(klass) == str: + if klass.startswith('list['): + sub_kls = re.match(r'list\[(.*)\]', klass).group(1) + return [self.__deserialize(sub_data, sub_kls) + for sub_data in data] + + if klass.startswith('dict('): + sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2) + return {k: self.__deserialize(v, sub_kls) + for k, v in six.iteritems(data)} + + # convert str to class + if klass in self.NATIVE_TYPES_MAPPING: + klass = self.NATIVE_TYPES_MAPPING[klass] + else: + klass = getattr(swagger_client.models, klass) + + if klass in self.PRIMITIVE_TYPES: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object(data) + elif klass == datetime.date: + return self.__deserialize_date(data) + elif klass == datetime.datetime: + return self.__deserialize_datatime(data) + else: + return self.__deserialize_model(data, klass) + + def call_api(self, resource_path, method, + path_params=None, query_params=None, header_params=None, + body=None, post_params=None, files=None, + response_type=None, auth_settings=None, async_req=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None): + """Makes the HTTP request (synchronous) and returns deserialized data. + + To make an async request, set the async_req parameter. + + :param resource_path: Path to method endpoint. + :param method: Method to call. + :param path_params: Path parameters in the url. + :param query_params: Query parameters in the url. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param auth_settings list: Auth Settings names for the request. + :param response: Response data type. + :param files dict: key -> filename, value -> filepath, + for `multipart/form-data`. + :param async_req bool: execute request asynchronously + :param _return_http_data_only: response data without head status code + and headers + :param collection_formats: dict of collection formats for path, query, + header, and post parameters. + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: + If async_req parameter is True, + the request will be called asynchronously. + The method will return the request thread. + If parameter async_req is False or missing, + then the method will return the response directly. + """ + if not async_req: + return self.__call_api(resource_path, method, + path_params, query_params, header_params, + body, post_params, files, + response_type, auth_settings, + _return_http_data_only, collection_formats, + _preload_content, _request_timeout) + else: + thread = self.pool.apply_async(self.__call_api, (resource_path, + method, path_params, query_params, + header_params, body, + post_params, files, + response_type, auth_settings, + _return_http_data_only, + collection_formats, + _preload_content, _request_timeout)) + return thread + + def request(self, method, url, query_params=None, headers=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + """Makes the HTTP request using RESTClient.""" + if method == "GET": + return self.rest_client.GET(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "HEAD": + return self.rest_client.HEAD(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "OPTIONS": + return self.rest_client.OPTIONS(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "POST": + return self.rest_client.POST(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PUT": + return self.rest_client.PUT(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PATCH": + return self.rest_client.PATCH(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "DELETE": + return self.rest_client.DELETE(url, + query_params=query_params, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + else: + raise ValueError( + "http method must be `GET`, `HEAD`, `OPTIONS`," + " `POST`, `PATCH`, `PUT` or `DELETE`." + ) + + def parameters_to_tuples(self, params, collection_formats): + """Get parameters as list of tuples, formatting collections. + + :param params: Parameters as dict or list of two-tuples + :param dict collection_formats: Parameter collection formats + :return: Parameters as list of tuples, collections formatted + """ + new_params = [] + if collection_formats is None: + collection_formats = {} + for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, value) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + new_params.append( + (k, delimiter.join(str(value) for value in v))) + else: + new_params.append((k, v)) + return new_params + + def prepare_post_parameters(self, post_params=None, files=None): + """Builds form parameters. + + :param post_params: Normal form parameters. + :param files: File parameters. + :return: Form parameters with files. + """ + params = [] + + if post_params: + params = post_params + + if files: + for k, v in six.iteritems(files): + if not v: + continue + file_names = v if type(v) is list else [v] + for n in file_names: + with open(n, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + mimetype = (mimetypes.guess_type(filename)[0] or + 'application/octet-stream') + params.append( + tuple([k, tuple([filename, filedata, mimetype])])) + + return params + + def select_header_accept(self, accepts): + """Returns `Accept` based on an array of accepts provided. + + :param accepts: List of headers. + :return: Accept (e.g. application/json). + """ + if not accepts: + return + + accepts = [x.lower() for x in accepts] + + if 'application/json' in accepts: + return 'application/json' + else: + return ', '.join(accepts) + + def select_header_content_type(self, content_types): + """Returns `Content-Type` based on an array of content_types provided. + + :param content_types: List of content-types. + :return: Content-Type (e.g. application/json). + """ + if not content_types: + return 'application/json' + + content_types = [x.lower() for x in content_types] + + if 'application/json' in content_types or '*/*' in content_types: + return 'application/json' + else: + return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """Updates header and query params based on authentication setting. + + :param headers: Header parameters dict to be updated. + :param querys: Query parameters tuple list to be updated. + :param auth_settings: Authentication setting identifiers list. + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = self.configuration.auth_settings().get(auth) + if auth_setting: + if not auth_setting['value']: + continue + elif auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys.append((auth_setting['key'], auth_setting['value'])) + else: + raise ValueError( + 'Authentication token must be in `query` or `header`' + ) + + def __deserialize_file(self, response): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + :param response: RESTResponse. + :return: file path. + """ + fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', + content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + response_data = response.data + with open(path, "wb") as f: + if isinstance(response_data, str): + # change str to bytes so we can write it + response_data = response_data.encode('utf-8') + f.write(response_data) + else: + f.write(response_data) + return path + + def __deserialize_primitive(self, data, klass): + """Deserializes string to primitive type. + + :param data: str. + :param klass: class literal. + + :return: int, long, float, str, bool. + """ + try: + return klass(data) + except UnicodeEncodeError: + return six.text_type(data) + except TypeError: + return data + + def __deserialize_object(self, value): + """Return a original value. + + :return: object. + """ + return value + + def __deserialize_date(self, string): + """Deserializes string to date. + + :param string: str. + :return: date. + """ + try: + from dateutil.parser import parse + return parse(string).date() + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason="Failed to parse `{0}` as date object".format(string) + ) + + def __deserialize_datatime(self, string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :return: datetime. + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as datetime object" + .format(string) + ) + ) + + def __hasattr(self, object, name): + return name in object.__class__.__dict__ + + def __deserialize_model(self, data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :param klass: class literal. + :return: model object. + """ + + if not klass.swagger_types and not self.__hasattr(klass, 'get_real_child_model'): + return data + + kwargs = {} + if klass.swagger_types is not None: + for attr, attr_type in six.iteritems(klass.swagger_types): + if (data is not None and + klass.attribute_map[attr] in data and + isinstance(data, (list, dict))): + value = data[klass.attribute_map[attr]] + kwargs[attr] = self.__deserialize(value, attr_type) + + instance = klass(**kwargs) + + if (isinstance(instance, dict) and + klass.swagger_types is not None and + isinstance(data, dict)): + for key, value in data.items(): + if key not in klass.swagger_types: + instance[key] = value + if self.__hasattr(instance, 'get_real_child_model'): + klass_name = instance.get_real_child_model(data) + if klass_name: + instance = self.__deserialize(data, klass_name) + return instance diff --git a/examples/demo9/python/mecapp/swagger_client/configuration.py b/examples/demo9/python/mecapp/swagger_client/configuration.py new file mode 100644 index 000000000..97eb12329 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/configuration.py @@ -0,0 +1,244 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import copy +import logging +import multiprocessing +import sys +import urllib3 + +import six +from six.moves import http_client as httplib + + +class TypeWithDefault(type): + def __init__(cls, name, bases, dct): + super(TypeWithDefault, cls).__init__(name, bases, dct) + cls._default = None + + def __call__(cls): + if cls._default is None: + cls._default = type.__call__(cls) + return copy.copy(cls._default) + + def set_default(cls, default): + cls._default = copy.copy(default) + + +class Configuration(six.with_metaclass(TypeWithDefault, object)): + """NOTE: This class is auto generated by the swagger code generator program. + + Ref: https://github.com/swagger-api/swagger-codegen + Do not edit the class manually. + """ + + def __init__(self): + """Constructor""" + # Default Base url + self.host = "http://localhost/sandbox-api/v1" + # Temp file folder for downloading files + self.temp_folder_path = None + + # Authentication Settings + # dict to store API key(s) + self.api_key = {} + # dict to store API prefix (e.g. Bearer) + self.api_key_prefix = {} + # function to refresh API key if expired + self.refresh_api_key_hook = None + # Username for HTTP basic authentication + self.username = "" + # Password for HTTP basic authentication + self.password = "" + # Logging Settings + self.logger = {} + self.logger["package_logger"] = logging.getLogger("swagger_client") + self.logger["urllib3_logger"] = logging.getLogger("urllib3") + # Log format + self.logger_format = '%(asctime)s %(levelname)s %(message)s' + # Log stream handler + self.logger_stream_handler = None + # Log file handler + self.logger_file_handler = None + # Debug file location + self.logger_file = None + # Debug switch + self.debug = False + + # SSL/TLS verification + # Set this to false to skip verifying SSL certificate when calling API + # from https server. + self.verify_ssl = True + # Set this to customize the certificate file to verify the peer. + self.ssl_ca_cert = None + # client certificate file + self.cert_file = None + # client key file + self.key_file = None + # Set this to True/False to enable/disable SSL hostname verification. + self.assert_hostname = None + + # urllib3 connection pool's maximum number of connections saved + # per pool. urllib3 uses 1 connection as default value, but this is + # not the best value when you are making a lot of possibly parallel + # requests to the same host, which is often the case here. + # cpu_count * 5 is used as default value to increase performance. + self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 + + # Proxy URL + self.proxy = None + # Safe chars for path_param + self.safe_chars_for_path_param = '' + + @property + def logger_file(self): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + return self.__logger_file + + @logger_file.setter + def logger_file(self, value): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + self.__logger_file = value + if self.__logger_file: + # If set logging file, + # then add file handler and remove stream handler. + self.logger_file_handler = logging.FileHandler(self.__logger_file) + self.logger_file_handler.setFormatter(self.logger_formatter) + for _, logger in six.iteritems(self.logger): + logger.addHandler(self.logger_file_handler) + if self.logger_stream_handler: + logger.removeHandler(self.logger_stream_handler) + else: + # If not set logging file, + # then add stream handler and remove file handler. + self.logger_stream_handler = logging.StreamHandler() + self.logger_stream_handler.setFormatter(self.logger_formatter) + for _, logger in six.iteritems(self.logger): + logger.addHandler(self.logger_stream_handler) + if self.logger_file_handler: + logger.removeHandler(self.logger_file_handler) + + @property + def debug(self): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + return self.__debug + + @debug.setter + def debug(self, value): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + self.__debug = value + if self.__debug: + # if debug status is True, turn on debug logging + for _, logger in six.iteritems(self.logger): + logger.setLevel(logging.DEBUG) + # turn on httplib debug + httplib.HTTPConnection.debuglevel = 1 + else: + # if debug status is False, turn off debug logging, + # setting log level to default `logging.WARNING` + for _, logger in six.iteritems(self.logger): + logger.setLevel(logging.WARNING) + # turn off httplib debug + httplib.HTTPConnection.debuglevel = 0 + + @property + def logger_format(self): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + return self.__logger_format + + @logger_format.setter + def logger_format(self, value): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + self.__logger_format = value + self.logger_formatter = logging.Formatter(self.__logger_format) + + def get_api_key_with_prefix(self, identifier): + """Gets API key (with prefix if set). + + :param identifier: The identifier of apiKey. + :return: The token for api key authentication. + """ + if self.refresh_api_key_hook: + self.refresh_api_key_hook(self) + + key = self.api_key.get(identifier) + if key: + prefix = self.api_key_prefix.get(identifier) + if prefix: + return "%s %s" % (prefix, key) + else: + return key + + def get_basic_auth_token(self): + """Gets HTTP basic authentication header (string). + + :return: The token for basic HTTP authentication. + """ + return urllib3.util.make_headers( + basic_auth=self.username + ':' + self.password + ).get('authorization') + + def auth_settings(self): + """Gets Auth Settings dict for api client. + + :return: The Auth Settings information dict. + """ + return { + } + + def to_debug_report(self): + """Gets the essential information for debugging. + + :return: The report for debugging. + """ + return "Python SDK Debug Report:\n"\ + "OS: {env}\n"\ + "Python Version: {pyversion}\n"\ + "Version of the API: 0.0.9\n"\ + "SDK Package Version: 1.0.0".\ + format(env=sys.platform, pyversion=sys.version) diff --git a/examples/demo9/python/mecapp/swagger_client/models/__init__.py b/examples/demo9/python/mecapp/swagger_client/models/__init__.py new file mode 100644 index 000000000..ce74c781a --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/__init__.py @@ -0,0 +1,53 @@ +# coding: utf-8 + +# flake8: noqa +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +# import models into model package +from swagger_client.models.application_info import ApplicationInfo +from swagger_client.models.cellular_domain_config import CellularDomainConfig +from swagger_client.models.cellular_poa_config import CellularPoaConfig +from swagger_client.models.connectivity_config import ConnectivityConfig +from swagger_client.models.cpu_config import CpuConfig +from swagger_client.models.d2d_config import D2dConfig +from swagger_client.models.dn_config import DNConfig +from swagger_client.models.deployment import Deployment +from swagger_client.models.domain import Domain +from swagger_client.models.egress_service import EgressService +from swagger_client.models.external_config import ExternalConfig +from swagger_client.models.geo_data import GeoData +from swagger_client.models.gpu_config import GpuConfig +from swagger_client.models.ingress_service import IngressService +from swagger_client.models.line_string import LineString +from swagger_client.models.memory_config import MemoryConfig +from swagger_client.models.namespace import Namespace +from swagger_client.models.network_characteristics import NetworkCharacteristics +from swagger_client.models.network_location import NetworkLocation +from swagger_client.models.oauth import Oauth +from swagger_client.models.physical_location import PhysicalLocation +from swagger_client.models.poa4_g_config import Poa4GConfig +from swagger_client.models.poa5_g_config import Poa5GConfig +from swagger_client.models.poa_wifi_config import PoaWifiConfig +from swagger_client.models.point import Point +from swagger_client.models.problem_details import ProblemDetails +from swagger_client.models.process import Process +from swagger_client.models.sandbox_app_instances import SandboxAppInstances +from swagger_client.models.sandbox_logs_subscriptions import SandboxLogsSubscriptions +from swagger_client.models.sandbox_mec_services import SandboxMecServices +from swagger_client.models.sandbox_network_scenario import SandboxNetworkScenario +from swagger_client.models.scenario import Scenario +from swagger_client.models.scenario_config import ScenarioConfig +from swagger_client.models.service_config import ServiceConfig +from swagger_client.models.service_port import ServicePort +from swagger_client.models.ue import UE +from swagger_client.models.zone import Zone diff --git a/examples/demo9/python/mecapp/swagger_client/models/application_info.py b/examples/demo9/python/mecapp/swagger_client/models/application_info.py new file mode 100644 index 000000000..c163eb034 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/application_info.py @@ -0,0 +1,232 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ApplicationInfo(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'name': 'str', + 'node_name': 'str', + 'type': 'str', + 'persist': 'bool' + } + + attribute_map = { + 'id': 'id', + 'name': 'name', + 'node_name': 'nodeName', + 'type': 'type', + 'persist': 'persist' + } + + def __init__(self, id=None, name=None, node_name=None, type=None, persist=None): # noqa: E501 + """ApplicationInfo - a model defined in Swagger""" # noqa: E501 + self._id = None + self._name = None + self._node_name = None + self._type = None + self._persist = None + self.discriminator = None + if id is not None: + self.id = id + self.name = name + self.node_name = node_name + if type is not None: + self.type = type + if persist is not None: + self.persist = persist + + @property + def id(self): + """Gets the id of this ApplicationInfo. # noqa: E501 + + Application Instance UUID # noqa: E501 + + :return: The id of this ApplicationInfo. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this ApplicationInfo. + + Application Instance UUID # noqa: E501 + + :param id: The id of this ApplicationInfo. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this ApplicationInfo. # noqa: E501 + + Application name # noqa: E501 + + :return: The name of this ApplicationInfo. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this ApplicationInfo. + + Application name # noqa: E501 + + :param name: The name of this ApplicationInfo. # noqa: E501 + :type: str + """ + if name is None: + raise ValueError("Invalid value for `name`, must not be `None`") # noqa: E501 + + self._name = name + + @property + def node_name(self): + """Gets the node_name of this ApplicationInfo. # noqa: E501 + + Name of node where application instance is running # noqa: E501 + + :return: The node_name of this ApplicationInfo. # noqa: E501 + :rtype: str + """ + return self._node_name + + @node_name.setter + def node_name(self, node_name): + """Sets the node_name of this ApplicationInfo. + + Name of node where application instance is running # noqa: E501 + + :param node_name: The node_name of this ApplicationInfo. # noqa: E501 + :type: str + """ + if node_name is None: + raise ValueError("Invalid value for `node_name`, must not be `None`") # noqa: E501 + + self._node_name = node_name + + @property + def type(self): + """Gets the type of this ApplicationInfo. # noqa: E501 + + Application Type # noqa: E501 + + :return: The type of this ApplicationInfo. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this ApplicationInfo. + + Application Type # noqa: E501 + + :param type: The type of this ApplicationInfo. # noqa: E501 + :type: str + """ + allowed_values = ["USER", "SYSTEM"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def persist(self): + """Gets the persist of this ApplicationInfo. # noqa: E501 + + Reserved for internal platform usage # noqa: E501 + + :return: The persist of this ApplicationInfo. # noqa: E501 + :rtype: bool + """ + return self._persist + + @persist.setter + def persist(self, persist): + """Sets the persist of this ApplicationInfo. + + Reserved for internal platform usage # noqa: E501 + + :param persist: The persist of this ApplicationInfo. # noqa: E501 + :type: bool + """ + + self._persist = persist + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ApplicationInfo, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ApplicationInfo): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/cellular_domain_config.py b/examples/demo9/python/mecapp/swagger_client/models/cellular_domain_config.py new file mode 100644 index 000000000..af1063450 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/cellular_domain_config.py @@ -0,0 +1,168 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class CellularDomainConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'mnc': 'str', + 'mcc': 'str', + 'default_cell_id': 'str' + } + + attribute_map = { + 'mnc': 'mnc', + 'mcc': 'mcc', + 'default_cell_id': 'defaultCellId' + } + + def __init__(self, mnc=None, mcc=None, default_cell_id=None): # noqa: E501 + """CellularDomainConfig - a model defined in Swagger""" # noqa: E501 + self._mnc = None + self._mcc = None + self._default_cell_id = None + self.discriminator = None + if mnc is not None: + self.mnc = mnc + if mcc is not None: + self.mcc = mcc + if default_cell_id is not None: + self.default_cell_id = default_cell_id + + @property + def mnc(self): + """Gets the mnc of this CellularDomainConfig. # noqa: E501 + + Mobile Network Code part of PLMN identity as defined in ETSI TS 136 413 # noqa: E501 + + :return: The mnc of this CellularDomainConfig. # noqa: E501 + :rtype: str + """ + return self._mnc + + @mnc.setter + def mnc(self, mnc): + """Sets the mnc of this CellularDomainConfig. + + Mobile Network Code part of PLMN identity as defined in ETSI TS 136 413 # noqa: E501 + + :param mnc: The mnc of this CellularDomainConfig. # noqa: E501 + :type: str + """ + + self._mnc = mnc + + @property + def mcc(self): + """Gets the mcc of this CellularDomainConfig. # noqa: E501 + + Mobile Country Code part of PLMN identity as defined in ETSI TS 136 413 # noqa: E501 + + :return: The mcc of this CellularDomainConfig. # noqa: E501 + :rtype: str + """ + return self._mcc + + @mcc.setter + def mcc(self, mcc): + """Sets the mcc of this CellularDomainConfig. + + Mobile Country Code part of PLMN identity as defined in ETSI TS 136 413 # noqa: E501 + + :param mcc: The mcc of this CellularDomainConfig. # noqa: E501 + :type: str + """ + + self._mcc = mcc + + @property + def default_cell_id(self): + """Gets the default_cell_id of this CellularDomainConfig. # noqa: E501 + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 if no cellId is defined for the cell or if not applicable # noqa: E501 + + :return: The default_cell_id of this CellularDomainConfig. # noqa: E501 + :rtype: str + """ + return self._default_cell_id + + @default_cell_id.setter + def default_cell_id(self, default_cell_id): + """Sets the default_cell_id of this CellularDomainConfig. + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 if no cellId is defined for the cell or if not applicable # noqa: E501 + + :param default_cell_id: The default_cell_id of this CellularDomainConfig. # noqa: E501 + :type: str + """ + + self._default_cell_id = default_cell_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(CellularDomainConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, CellularDomainConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/cellular_poa_config.py b/examples/demo9/python/mecapp/swagger_client/models/cellular_poa_config.py new file mode 100644 index 000000000..4477f31d9 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/cellular_poa_config.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class CellularPoaConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'cell_id': 'str' + } + + attribute_map = { + 'cell_id': 'cellId' + } + + def __init__(self, cell_id=None): # noqa: E501 + """CellularPoaConfig - a model defined in Swagger""" # noqa: E501 + self._cell_id = None + self.discriminator = None + if cell_id is not None: + self.cell_id = cell_id + + @property + def cell_id(self): + """Gets the cell_id of this CellularPoaConfig. # noqa: E501 + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell # noqa: E501 + + :return: The cell_id of this CellularPoaConfig. # noqa: E501 + :rtype: str + """ + return self._cell_id + + @cell_id.setter + def cell_id(self, cell_id): + """Sets the cell_id of this CellularPoaConfig. + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell # noqa: E501 + + :param cell_id: The cell_id of this CellularPoaConfig. # noqa: E501 + :type: str + """ + + self._cell_id = cell_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(CellularPoaConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, CellularPoaConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/connectivity_config.py b/examples/demo9/python/mecapp/swagger_client/models/connectivity_config.py new file mode 100644 index 000000000..3a27d7475 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/connectivity_config.py @@ -0,0 +1,118 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ConnectivityConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'model': 'str' + } + + attribute_map = { + 'model': 'model' + } + + def __init__(self, model=None): # noqa: E501 + """ConnectivityConfig - a model defined in Swagger""" # noqa: E501 + self._model = None + self.discriminator = None + if model is not None: + self.model = model + + @property + def model(self): + """Gets the model of this ConnectivityConfig. # noqa: E501 + + Connectivity Model:

  • OPEN: Any node in the scenario can communicate with any node
  • PDU: Terminal nodes (UE) require a PDU session to the target DN # noqa: E501 + + :return: The model of this ConnectivityConfig. # noqa: E501 + :rtype: str + """ + return self._model + + @model.setter + def model(self, model): + """Sets the model of this ConnectivityConfig. + + Connectivity Model:
  • OPEN: Any node in the scenario can communicate with any node
  • PDU: Terminal nodes (UE) require a PDU session to the target DN # noqa: E501 + + :param model: The model of this ConnectivityConfig. # noqa: E501 + :type: str + """ + allowed_values = ["OPEN", "PDU"] # noqa: E501 + if model not in allowed_values: + raise ValueError( + "Invalid value for `model` ({0}), must be one of {1}" # noqa: E501 + .format(model, allowed_values) + ) + + self._model = model + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ConnectivityConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ConnectivityConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/cpu_config.py b/examples/demo9/python/mecapp/swagger_client/models/cpu_config.py new file mode 100644 index 000000000..ee696b19f --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/cpu_config.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class CpuConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'min': 'float', + 'max': 'float' + } + + attribute_map = { + 'min': 'min', + 'max': 'max' + } + + def __init__(self, min=None, max=None): # noqa: E501 + """CpuConfig - a model defined in Swagger""" # noqa: E501 + self._min = None + self._max = None + self.discriminator = None + if min is not None: + self.min = min + if max is not None: + self.max = max + + @property + def min(self): + """Gets the min of this CpuConfig. # noqa: E501 + + Minimum requested CPU # noqa: E501 + + :return: The min of this CpuConfig. # noqa: E501 + :rtype: float + """ + return self._min + + @min.setter + def min(self, min): + """Sets the min of this CpuConfig. + + Minimum requested CPU # noqa: E501 + + :param min: The min of this CpuConfig. # noqa: E501 + :type: float + """ + + self._min = min + + @property + def max(self): + """Gets the max of this CpuConfig. # noqa: E501 + + Maximum requested CPU # noqa: E501 + + :return: The max of this CpuConfig. # noqa: E501 + :rtype: float + """ + return self._max + + @max.setter + def max(self, max): + """Sets the max of this CpuConfig. + + Maximum requested CPU # noqa: E501 + + :param max: The max of this CpuConfig. # noqa: E501 + :type: float + """ + + self._max = max + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(CpuConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, CpuConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/d2d_config.py b/examples/demo9/python/mecapp/swagger_client/models/d2d_config.py new file mode 100644 index 000000000..628d03bcc --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/d2d_config.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class D2dConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'd2d_max_distance': 'float', + 'disable_d2d_via_network': 'bool' + } + + attribute_map = { + 'd2d_max_distance': 'd2dMaxDistance', + 'disable_d2d_via_network': 'disableD2dViaNetwork' + } + + def __init__(self, d2d_max_distance=None, disable_d2d_via_network=None): # noqa: E501 + """D2dConfig - a model defined in Swagger""" # noqa: E501 + self._d2d_max_distance = None + self._disable_d2d_via_network = None + self.discriminator = None + if d2d_max_distance is not None: + self.d2d_max_distance = d2d_max_distance + if disable_d2d_via_network is not None: + self.disable_d2d_via_network = disable_d2d_via_network + + @property + def d2d_max_distance(self): + """Gets the d2d_max_distance of this D2dConfig. # noqa: E501 + + Maximum distance for D2D. Default distance is 100m # noqa: E501 + + :return: The d2d_max_distance of this D2dConfig. # noqa: E501 + :rtype: float + """ + return self._d2d_max_distance + + @d2d_max_distance.setter + def d2d_max_distance(self, d2d_max_distance): + """Sets the d2d_max_distance of this D2dConfig. + + Maximum distance for D2D. Default distance is 100m # noqa: E501 + + :param d2d_max_distance: The d2d_max_distance of this D2dConfig. # noqa: E501 + :type: float + """ + + self._d2d_max_distance = d2d_max_distance + + @property + def disable_d2d_via_network(self): + """Gets the disable_d2d_via_network of this D2dConfig. # noqa: E501 + + Enable-Disable D2D via network. Default value is false # noqa: E501 + + :return: The disable_d2d_via_network of this D2dConfig. # noqa: E501 + :rtype: bool + """ + return self._disable_d2d_via_network + + @disable_d2d_via_network.setter + def disable_d2d_via_network(self, disable_d2d_via_network): + """Sets the disable_d2d_via_network of this D2dConfig. + + Enable-Disable D2D via network. Default value is false # noqa: E501 + + :param disable_d2d_via_network: The disable_d2d_via_network of this D2dConfig. # noqa: E501 + :type: bool + """ + + self._disable_d2d_via_network = disable_d2d_via_network + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(D2dConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, D2dConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/deployment.py b/examples/demo9/python/mecapp/swagger_client/models/deployment.py new file mode 100644 index 000000000..61aa2911c --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/deployment.py @@ -0,0 +1,356 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Deployment(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'net_char': 'NetworkCharacteristics', + 'connectivity': 'ConnectivityConfig', + 'd2d': 'D2dConfig', + 'inter_domain_latency': 'int', + 'inter_domain_latency_variation': 'int', + 'inter_domain_throughput': 'int', + 'inter_domain_packet_loss': 'float', + 'meta': 'dict(str, str)', + 'user_meta': 'dict(str, str)', + 'domains': 'list[Domain]' + } + + attribute_map = { + 'net_char': 'netChar', + 'connectivity': 'connectivity', + 'd2d': 'd2d', + 'inter_domain_latency': 'interDomainLatency', + 'inter_domain_latency_variation': 'interDomainLatencyVariation', + 'inter_domain_throughput': 'interDomainThroughput', + 'inter_domain_packet_loss': 'interDomainPacketLoss', + 'meta': 'meta', + 'user_meta': 'userMeta', + 'domains': 'domains' + } + + def __init__(self, net_char=None, connectivity=None, d2d=None, inter_domain_latency=None, inter_domain_latency_variation=None, inter_domain_throughput=None, inter_domain_packet_loss=None, meta=None, user_meta=None, domains=None): # noqa: E501 + """Deployment - a model defined in Swagger""" # noqa: E501 + self._net_char = None + self._connectivity = None + self._d2d = None + self._inter_domain_latency = None + self._inter_domain_latency_variation = None + self._inter_domain_throughput = None + self._inter_domain_packet_loss = None + self._meta = None + self._user_meta = None + self._domains = None + self.discriminator = None + if net_char is not None: + self.net_char = net_char + if connectivity is not None: + self.connectivity = connectivity + if d2d is not None: + self.d2d = d2d + if inter_domain_latency is not None: + self.inter_domain_latency = inter_domain_latency + if inter_domain_latency_variation is not None: + self.inter_domain_latency_variation = inter_domain_latency_variation + if inter_domain_throughput is not None: + self.inter_domain_throughput = inter_domain_throughput + if inter_domain_packet_loss is not None: + self.inter_domain_packet_loss = inter_domain_packet_loss + if meta is not None: + self.meta = meta + if user_meta is not None: + self.user_meta = user_meta + if domains is not None: + self.domains = domains + + @property + def net_char(self): + """Gets the net_char of this Deployment. # noqa: E501 + + + :return: The net_char of this Deployment. # noqa: E501 + :rtype: NetworkCharacteristics + """ + return self._net_char + + @net_char.setter + def net_char(self, net_char): + """Sets the net_char of this Deployment. + + + :param net_char: The net_char of this Deployment. # noqa: E501 + :type: NetworkCharacteristics + """ + + self._net_char = net_char + + @property + def connectivity(self): + """Gets the connectivity of this Deployment. # noqa: E501 + + + :return: The connectivity of this Deployment. # noqa: E501 + :rtype: ConnectivityConfig + """ + return self._connectivity + + @connectivity.setter + def connectivity(self, connectivity): + """Sets the connectivity of this Deployment. + + + :param connectivity: The connectivity of this Deployment. # noqa: E501 + :type: ConnectivityConfig + """ + + self._connectivity = connectivity + + @property + def d2d(self): + """Gets the d2d of this Deployment. # noqa: E501 + + + :return: The d2d of this Deployment. # noqa: E501 + :rtype: D2dConfig + """ + return self._d2d + + @d2d.setter + def d2d(self, d2d): + """Sets the d2d of this Deployment. + + + :param d2d: The d2d of this Deployment. # noqa: E501 + :type: D2dConfig + """ + + self._d2d = d2d + + @property + def inter_domain_latency(self): + """Gets the inter_domain_latency of this Deployment. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :return: The inter_domain_latency of this Deployment. # noqa: E501 + :rtype: int + """ + return self._inter_domain_latency + + @inter_domain_latency.setter + def inter_domain_latency(self, inter_domain_latency): + """Sets the inter_domain_latency of this Deployment. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :param inter_domain_latency: The inter_domain_latency of this Deployment. # noqa: E501 + :type: int + """ + + self._inter_domain_latency = inter_domain_latency + + @property + def inter_domain_latency_variation(self): + """Gets the inter_domain_latency_variation of this Deployment. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :return: The inter_domain_latency_variation of this Deployment. # noqa: E501 + :rtype: int + """ + return self._inter_domain_latency_variation + + @inter_domain_latency_variation.setter + def inter_domain_latency_variation(self, inter_domain_latency_variation): + """Sets the inter_domain_latency_variation of this Deployment. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :param inter_domain_latency_variation: The inter_domain_latency_variation of this Deployment. # noqa: E501 + :type: int + """ + + self._inter_domain_latency_variation = inter_domain_latency_variation + + @property + def inter_domain_throughput(self): + """Gets the inter_domain_throughput of this Deployment. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :return: The inter_domain_throughput of this Deployment. # noqa: E501 + :rtype: int + """ + return self._inter_domain_throughput + + @inter_domain_throughput.setter + def inter_domain_throughput(self, inter_domain_throughput): + """Sets the inter_domain_throughput of this Deployment. + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :param inter_domain_throughput: The inter_domain_throughput of this Deployment. # noqa: E501 + :type: int + """ + + self._inter_domain_throughput = inter_domain_throughput + + @property + def inter_domain_packet_loss(self): + """Gets the inter_domain_packet_loss of this Deployment. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :return: The inter_domain_packet_loss of this Deployment. # noqa: E501 + :rtype: float + """ + return self._inter_domain_packet_loss + + @inter_domain_packet_loss.setter + def inter_domain_packet_loss(self, inter_domain_packet_loss): + """Sets the inter_domain_packet_loss of this Deployment. + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :param inter_domain_packet_loss: The inter_domain_packet_loss of this Deployment. # noqa: E501 + :type: float + """ + + self._inter_domain_packet_loss = inter_domain_packet_loss + + @property + def meta(self): + """Gets the meta of this Deployment. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The meta of this Deployment. # noqa: E501 + :rtype: dict(str, str) + """ + return self._meta + + @meta.setter + def meta(self, meta): + """Sets the meta of this Deployment. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param meta: The meta of this Deployment. # noqa: E501 + :type: dict(str, str) + """ + + self._meta = meta + + @property + def user_meta(self): + """Gets the user_meta of this Deployment. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The user_meta of this Deployment. # noqa: E501 + :rtype: dict(str, str) + """ + return self._user_meta + + @user_meta.setter + def user_meta(self, user_meta): + """Sets the user_meta of this Deployment. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param user_meta: The user_meta of this Deployment. # noqa: E501 + :type: dict(str, str) + """ + + self._user_meta = user_meta + + @property + def domains(self): + """Gets the domains of this Deployment. # noqa: E501 + + + :return: The domains of this Deployment. # noqa: E501 + :rtype: list[Domain] + """ + return self._domains + + @domains.setter + def domains(self, domains): + """Sets the domains of this Deployment. + + + :param domains: The domains of this Deployment. # noqa: E501 + :type: list[Domain] + """ + + self._domains = domains + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Deployment, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Deployment): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/dn_config.py b/examples/demo9/python/mecapp/swagger_client/models/dn_config.py new file mode 100644 index 000000000..7ea5e765c --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/dn_config.py @@ -0,0 +1,168 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class DNConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'dnn': 'str', + 'ladn': 'bool', + 'ecsp': 'str' + } + + attribute_map = { + 'dnn': 'dnn', + 'ladn': 'ladn', + 'ecsp': 'ecsp' + } + + def __init__(self, dnn=None, ladn=None, ecsp=None): # noqa: E501 + """DNConfig - a model defined in Swagger""" # noqa: E501 + self._dnn = None + self._ladn = None + self._ecsp = None + self.discriminator = None + if dnn is not None: + self.dnn = dnn + if ladn is not None: + self.ladn = ladn + if ecsp is not None: + self.ecsp = ecsp + + @property + def dnn(self): + """Gets the dnn of this DNConfig. # noqa: E501 + + Data Network Name # noqa: E501 + + :return: The dnn of this DNConfig. # noqa: E501 + :rtype: str + """ + return self._dnn + + @dnn.setter + def dnn(self, dnn): + """Sets the dnn of this DNConfig. + + Data Network Name # noqa: E501 + + :param dnn: The dnn of this DNConfig. # noqa: E501 + :type: str + """ + + self._dnn = dnn + + @property + def ladn(self): + """Gets the ladn of this DNConfig. # noqa: E501 + + true: Data network serves local area only false: Data network is not limited to local area # noqa: E501 + + :return: The ladn of this DNConfig. # noqa: E501 + :rtype: bool + """ + return self._ladn + + @ladn.setter + def ladn(self, ladn): + """Sets the ladn of this DNConfig. + + true: Data network serves local area only false: Data network is not limited to local area # noqa: E501 + + :param ladn: The ladn of this DNConfig. # noqa: E501 + :type: bool + """ + + self._ladn = ladn + + @property + def ecsp(self): + """Gets the ecsp of this DNConfig. # noqa: E501 + + Edge Compute Service Provider # noqa: E501 + + :return: The ecsp of this DNConfig. # noqa: E501 + :rtype: str + """ + return self._ecsp + + @ecsp.setter + def ecsp(self, ecsp): + """Sets the ecsp of this DNConfig. + + Edge Compute Service Provider # noqa: E501 + + :param ecsp: The ecsp of this DNConfig. # noqa: E501 + :type: str + """ + + self._ecsp = ecsp + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(DNConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, DNConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/domain.py b/examples/demo9/python/mecapp/swagger_client/models/domain.py new file mode 100644 index 000000000..19d95e04d --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/domain.py @@ -0,0 +1,420 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Domain(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'name': 'str', + 'type': 'str', + 'net_char': 'NetworkCharacteristics', + 'inter_zone_latency': 'int', + 'inter_zone_latency_variation': 'int', + 'inter_zone_throughput': 'int', + 'inter_zone_packet_loss': 'float', + 'meta': 'dict(str, str)', + 'user_meta': 'dict(str, str)', + 'cellular_domain_config': 'CellularDomainConfig', + 'zones': 'list[Zone]' + } + + attribute_map = { + 'id': 'id', + 'name': 'name', + 'type': 'type', + 'net_char': 'netChar', + 'inter_zone_latency': 'interZoneLatency', + 'inter_zone_latency_variation': 'interZoneLatencyVariation', + 'inter_zone_throughput': 'interZoneThroughput', + 'inter_zone_packet_loss': 'interZonePacketLoss', + 'meta': 'meta', + 'user_meta': 'userMeta', + 'cellular_domain_config': 'cellularDomainConfig', + 'zones': 'zones' + } + + def __init__(self, id=None, name=None, type=None, net_char=None, inter_zone_latency=None, inter_zone_latency_variation=None, inter_zone_throughput=None, inter_zone_packet_loss=None, meta=None, user_meta=None, cellular_domain_config=None, zones=None): # noqa: E501 + """Domain - a model defined in Swagger""" # noqa: E501 + self._id = None + self._name = None + self._type = None + self._net_char = None + self._inter_zone_latency = None + self._inter_zone_latency_variation = None + self._inter_zone_throughput = None + self._inter_zone_packet_loss = None + self._meta = None + self._user_meta = None + self._cellular_domain_config = None + self._zones = None + self.discriminator = None + if id is not None: + self.id = id + if name is not None: + self.name = name + if type is not None: + self.type = type + if net_char is not None: + self.net_char = net_char + if inter_zone_latency is not None: + self.inter_zone_latency = inter_zone_latency + if inter_zone_latency_variation is not None: + self.inter_zone_latency_variation = inter_zone_latency_variation + if inter_zone_throughput is not None: + self.inter_zone_throughput = inter_zone_throughput + if inter_zone_packet_loss is not None: + self.inter_zone_packet_loss = inter_zone_packet_loss + if meta is not None: + self.meta = meta + if user_meta is not None: + self.user_meta = user_meta + if cellular_domain_config is not None: + self.cellular_domain_config = cellular_domain_config + if zones is not None: + self.zones = zones + + @property + def id(self): + """Gets the id of this Domain. # noqa: E501 + + Unique domain ID # noqa: E501 + + :return: The id of this Domain. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this Domain. + + Unique domain ID # noqa: E501 + + :param id: The id of this Domain. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this Domain. # noqa: E501 + + Domain name # noqa: E501 + + :return: The name of this Domain. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this Domain. + + Domain name # noqa: E501 + + :param name: The name of this Domain. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def type(self): + """Gets the type of this Domain. # noqa: E501 + + Domain type # noqa: E501 + + :return: The type of this Domain. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this Domain. + + Domain type # noqa: E501 + + :param type: The type of this Domain. # noqa: E501 + :type: str + """ + allowed_values = ["OPERATOR", "OPERATOR-CELLULAR", "PUBLIC"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def net_char(self): + """Gets the net_char of this Domain. # noqa: E501 + + + :return: The net_char of this Domain. # noqa: E501 + :rtype: NetworkCharacteristics + """ + return self._net_char + + @net_char.setter + def net_char(self, net_char): + """Sets the net_char of this Domain. + + + :param net_char: The net_char of this Domain. # noqa: E501 + :type: NetworkCharacteristics + """ + + self._net_char = net_char + + @property + def inter_zone_latency(self): + """Gets the inter_zone_latency of this Domain. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :return: The inter_zone_latency of this Domain. # noqa: E501 + :rtype: int + """ + return self._inter_zone_latency + + @inter_zone_latency.setter + def inter_zone_latency(self, inter_zone_latency): + """Sets the inter_zone_latency of this Domain. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :param inter_zone_latency: The inter_zone_latency of this Domain. # noqa: E501 + :type: int + """ + + self._inter_zone_latency = inter_zone_latency + + @property + def inter_zone_latency_variation(self): + """Gets the inter_zone_latency_variation of this Domain. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :return: The inter_zone_latency_variation of this Domain. # noqa: E501 + :rtype: int + """ + return self._inter_zone_latency_variation + + @inter_zone_latency_variation.setter + def inter_zone_latency_variation(self, inter_zone_latency_variation): + """Sets the inter_zone_latency_variation of this Domain. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :param inter_zone_latency_variation: The inter_zone_latency_variation of this Domain. # noqa: E501 + :type: int + """ + + self._inter_zone_latency_variation = inter_zone_latency_variation + + @property + def inter_zone_throughput(self): + """Gets the inter_zone_throughput of this Domain. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :return: The inter_zone_throughput of this Domain. # noqa: E501 + :rtype: int + """ + return self._inter_zone_throughput + + @inter_zone_throughput.setter + def inter_zone_throughput(self, inter_zone_throughput): + """Sets the inter_zone_throughput of this Domain. + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :param inter_zone_throughput: The inter_zone_throughput of this Domain. # noqa: E501 + :type: int + """ + + self._inter_zone_throughput = inter_zone_throughput + + @property + def inter_zone_packet_loss(self): + """Gets the inter_zone_packet_loss of this Domain. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :return: The inter_zone_packet_loss of this Domain. # noqa: E501 + :rtype: float + """ + return self._inter_zone_packet_loss + + @inter_zone_packet_loss.setter + def inter_zone_packet_loss(self, inter_zone_packet_loss): + """Sets the inter_zone_packet_loss of this Domain. + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :param inter_zone_packet_loss: The inter_zone_packet_loss of this Domain. # noqa: E501 + :type: float + """ + + self._inter_zone_packet_loss = inter_zone_packet_loss + + @property + def meta(self): + """Gets the meta of this Domain. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The meta of this Domain. # noqa: E501 + :rtype: dict(str, str) + """ + return self._meta + + @meta.setter + def meta(self, meta): + """Sets the meta of this Domain. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param meta: The meta of this Domain. # noqa: E501 + :type: dict(str, str) + """ + + self._meta = meta + + @property + def user_meta(self): + """Gets the user_meta of this Domain. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The user_meta of this Domain. # noqa: E501 + :rtype: dict(str, str) + """ + return self._user_meta + + @user_meta.setter + def user_meta(self, user_meta): + """Sets the user_meta of this Domain. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param user_meta: The user_meta of this Domain. # noqa: E501 + :type: dict(str, str) + """ + + self._user_meta = user_meta + + @property + def cellular_domain_config(self): + """Gets the cellular_domain_config of this Domain. # noqa: E501 + + + :return: The cellular_domain_config of this Domain. # noqa: E501 + :rtype: CellularDomainConfig + """ + return self._cellular_domain_config + + @cellular_domain_config.setter + def cellular_domain_config(self, cellular_domain_config): + """Sets the cellular_domain_config of this Domain. + + + :param cellular_domain_config: The cellular_domain_config of this Domain. # noqa: E501 + :type: CellularDomainConfig + """ + + self._cellular_domain_config = cellular_domain_config + + @property + def zones(self): + """Gets the zones of this Domain. # noqa: E501 + + + :return: The zones of this Domain. # noqa: E501 + :rtype: list[Zone] + """ + return self._zones + + @zones.setter + def zones(self, zones): + """Sets the zones of this Domain. + + + :param zones: The zones of this Domain. # noqa: E501 + :type: list[Zone] + """ + + self._zones = zones + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Domain, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Domain): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/egress_service.py b/examples/demo9/python/mecapp/swagger_client/models/egress_service.py new file mode 100644 index 000000000..deb3ce4d6 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/egress_service.py @@ -0,0 +1,224 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class EgressService(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'name': 'str', + 'me_svc_name': 'str', + 'ip': 'str', + 'port': 'int', + 'protocol': 'str' + } + + attribute_map = { + 'name': 'name', + 'me_svc_name': 'meSvcName', + 'ip': 'ip', + 'port': 'port', + 'protocol': 'protocol' + } + + def __init__(self, name=None, me_svc_name=None, ip=None, port=None, protocol=None): # noqa: E501 + """EgressService - a model defined in Swagger""" # noqa: E501 + self._name = None + self._me_svc_name = None + self._ip = None + self._port = None + self._protocol = None + self.discriminator = None + if name is not None: + self.name = name + if me_svc_name is not None: + self.me_svc_name = me_svc_name + if ip is not None: + self.ip = ip + if port is not None: + self.port = port + if protocol is not None: + self.protocol = protocol + + @property + def name(self): + """Gets the name of this EgressService. # noqa: E501 + + Service name # noqa: E501 + + :return: The name of this EgressService. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this EgressService. + + Service name # noqa: E501 + + :param name: The name of this EgressService. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def me_svc_name(self): + """Gets the me_svc_name of this EgressService. # noqa: E501 + + Multi-Edge service name, if any # noqa: E501 + + :return: The me_svc_name of this EgressService. # noqa: E501 + :rtype: str + """ + return self._me_svc_name + + @me_svc_name.setter + def me_svc_name(self, me_svc_name): + """Sets the me_svc_name of this EgressService. + + Multi-Edge service name, if any # noqa: E501 + + :param me_svc_name: The me_svc_name of this EgressService. # noqa: E501 + :type: str + """ + + self._me_svc_name = me_svc_name + + @property + def ip(self): + """Gets the ip of this EgressService. # noqa: E501 + + External node IP address # noqa: E501 + + :return: The ip of this EgressService. # noqa: E501 + :rtype: str + """ + return self._ip + + @ip.setter + def ip(self, ip): + """Sets the ip of this EgressService. + + External node IP address # noqa: E501 + + :param ip: The ip of this EgressService. # noqa: E501 + :type: str + """ + + self._ip = ip + + @property + def port(self): + """Gets the port of this EgressService. # noqa: E501 + + Service port number # noqa: E501 + + :return: The port of this EgressService. # noqa: E501 + :rtype: int + """ + return self._port + + @port.setter + def port(self, port): + """Sets the port of this EgressService. + + Service port number # noqa: E501 + + :param port: The port of this EgressService. # noqa: E501 + :type: int + """ + + self._port = port + + @property + def protocol(self): + """Gets the protocol of this EgressService. # noqa: E501 + + Service protocol (TCP or UDP) # noqa: E501 + + :return: The protocol of this EgressService. # noqa: E501 + :rtype: str + """ + return self._protocol + + @protocol.setter + def protocol(self, protocol): + """Sets the protocol of this EgressService. + + Service protocol (TCP or UDP) # noqa: E501 + + :param protocol: The protocol of this EgressService. # noqa: E501 + :type: str + """ + + self._protocol = protocol + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(EgressService, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, EgressService): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/external_config.py b/examples/demo9/python/mecapp/swagger_client/models/external_config.py new file mode 100644 index 000000000..4450e3928 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/external_config.py @@ -0,0 +1,136 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ExternalConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'ingress_service_map': 'list[IngressService]', + 'egress_service_map': 'list[EgressService]' + } + + attribute_map = { + 'ingress_service_map': 'ingressServiceMap', + 'egress_service_map': 'egressServiceMap' + } + + def __init__(self, ingress_service_map=None, egress_service_map=None): # noqa: E501 + """ExternalConfig - a model defined in Swagger""" # noqa: E501 + self._ingress_service_map = None + self._egress_service_map = None + self.discriminator = None + if ingress_service_map is not None: + self.ingress_service_map = ingress_service_map + if egress_service_map is not None: + self.egress_service_map = egress_service_map + + @property + def ingress_service_map(self): + """Gets the ingress_service_map of this ExternalConfig. # noqa: E501 + + + :return: The ingress_service_map of this ExternalConfig. # noqa: E501 + :rtype: list[IngressService] + """ + return self._ingress_service_map + + @ingress_service_map.setter + def ingress_service_map(self, ingress_service_map): + """Sets the ingress_service_map of this ExternalConfig. + + + :param ingress_service_map: The ingress_service_map of this ExternalConfig. # noqa: E501 + :type: list[IngressService] + """ + + self._ingress_service_map = ingress_service_map + + @property + def egress_service_map(self): + """Gets the egress_service_map of this ExternalConfig. # noqa: E501 + + + :return: The egress_service_map of this ExternalConfig. # noqa: E501 + :rtype: list[EgressService] + """ + return self._egress_service_map + + @egress_service_map.setter + def egress_service_map(self, egress_service_map): + """Sets the egress_service_map of this ExternalConfig. + + + :param egress_service_map: The egress_service_map of this ExternalConfig. # noqa: E501 + :type: list[EgressService] + """ + + self._egress_service_map = egress_service_map + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ExternalConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ExternalConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/geo_data.py b/examples/demo9/python/mecapp/swagger_client/models/geo_data.py new file mode 100644 index 000000000..3497469eb --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/geo_data.py @@ -0,0 +1,278 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class GeoData(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'location': 'Point', + 'radius': 'float', + 'path': 'LineString', + 'eop_mode': 'str', + 'velocity': 'float', + 'd2d_in_range': 'list[str]', + 'poa_in_range': 'list[str]' + } + + attribute_map = { + 'location': 'location', + 'radius': 'radius', + 'path': 'path', + 'eop_mode': 'eopMode', + 'velocity': 'velocity', + 'd2d_in_range': 'd2dInRange', + 'poa_in_range': 'poaInRange' + } + + def __init__(self, location=None, radius=None, path=None, eop_mode=None, velocity=None, d2d_in_range=None, poa_in_range=None): # noqa: E501 + """GeoData - a model defined in Swagger""" # noqa: E501 + self._location = None + self._radius = None + self._path = None + self._eop_mode = None + self._velocity = None + self._d2d_in_range = None + self._poa_in_range = None + self.discriminator = None + if location is not None: + self.location = location + if radius is not None: + self.radius = radius + if path is not None: + self.path = path + if eop_mode is not None: + self.eop_mode = eop_mode + if velocity is not None: + self.velocity = velocity + if d2d_in_range is not None: + self.d2d_in_range = d2d_in_range + if poa_in_range is not None: + self.poa_in_range = poa_in_range + + @property + def location(self): + """Gets the location of this GeoData. # noqa: E501 + + + :return: The location of this GeoData. # noqa: E501 + :rtype: Point + """ + return self._location + + @location.setter + def location(self, location): + """Sets the location of this GeoData. + + + :param location: The location of this GeoData. # noqa: E501 + :type: Point + """ + + self._location = location + + @property + def radius(self): + """Gets the radius of this GeoData. # noqa: E501 + + Optional - Radius (in meters) around the location # noqa: E501 + + :return: The radius of this GeoData. # noqa: E501 + :rtype: float + """ + return self._radius + + @radius.setter + def radius(self, radius): + """Sets the radius of this GeoData. + + Optional - Radius (in meters) around the location # noqa: E501 + + :param radius: The radius of this GeoData. # noqa: E501 + :type: float + """ + + self._radius = radius + + @property + def path(self): + """Gets the path of this GeoData. # noqa: E501 + + + :return: The path of this GeoData. # noqa: E501 + :rtype: LineString + """ + return self._path + + @path.setter + def path(self, path): + """Sets the path of this GeoData. + + + :param path: The path of this GeoData. # noqa: E501 + :type: LineString + """ + + self._path = path + + @property + def eop_mode(self): + """Gets the eop_mode of this GeoData. # noqa: E501 + + End-of-Path mode:
  • LOOP: When path endpoint is reached, start over from the beginning
  • REVERSE: When path endpoint is reached, return on the reverse path # noqa: E501 + + :return: The eop_mode of this GeoData. # noqa: E501 + :rtype: str + """ + return self._eop_mode + + @eop_mode.setter + def eop_mode(self, eop_mode): + """Sets the eop_mode of this GeoData. + + End-of-Path mode:
  • LOOP: When path endpoint is reached, start over from the beginning
  • REVERSE: When path endpoint is reached, return on the reverse path # noqa: E501 + + :param eop_mode: The eop_mode of this GeoData. # noqa: E501 + :type: str + """ + allowed_values = ["LOOP", "REVERSE"] # noqa: E501 + if eop_mode not in allowed_values: + raise ValueError( + "Invalid value for `eop_mode` ({0}), must be one of {1}" # noqa: E501 + .format(eop_mode, allowed_values) + ) + + self._eop_mode = eop_mode + + @property + def velocity(self): + """Gets the velocity of this GeoData. # noqa: E501 + + Speed of movement along path in m/s # noqa: E501 + + :return: The velocity of this GeoData. # noqa: E501 + :rtype: float + """ + return self._velocity + + @velocity.setter + def velocity(self, velocity): + """Sets the velocity of this GeoData. + + Speed of movement along path in m/s # noqa: E501 + + :param velocity: The velocity of this GeoData. # noqa: E501 + :type: float + """ + + self._velocity = velocity + + @property + def d2d_in_range(self): + """Gets the d2d_in_range of this GeoData. # noqa: E501 + + + :return: The d2d_in_range of this GeoData. # noqa: E501 + :rtype: list[str] + """ + return self._d2d_in_range + + @d2d_in_range.setter + def d2d_in_range(self, d2d_in_range): + """Sets the d2d_in_range of this GeoData. + + + :param d2d_in_range: The d2d_in_range of this GeoData. # noqa: E501 + :type: list[str] + """ + + self._d2d_in_range = d2d_in_range + + @property + def poa_in_range(self): + """Gets the poa_in_range of this GeoData. # noqa: E501 + + + :return: The poa_in_range of this GeoData. # noqa: E501 + :rtype: list[str] + """ + return self._poa_in_range + + @poa_in_range.setter + def poa_in_range(self, poa_in_range): + """Sets the poa_in_range of this GeoData. + + + :param poa_in_range: The poa_in_range of this GeoData. # noqa: E501 + :type: list[str] + """ + + self._poa_in_range = poa_in_range + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(GeoData, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, GeoData): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/gpu_config.py b/examples/demo9/python/mecapp/swagger_client/models/gpu_config.py new file mode 100644 index 000000000..89cbdd5cb --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/gpu_config.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class GpuConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'type': 'str', + 'count': 'int' + } + + attribute_map = { + 'type': 'type', + 'count': 'count' + } + + def __init__(self, type=None, count=None): # noqa: E501 + """GpuConfig - a model defined in Swagger""" # noqa: E501 + self._type = None + self._count = None + self.discriminator = None + if type is not None: + self.type = type + if count is not None: + self.count = count + + @property + def type(self): + """Gets the type of this GpuConfig. # noqa: E501 + + Requested GPU type # noqa: E501 + + :return: The type of this GpuConfig. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this GpuConfig. + + Requested GPU type # noqa: E501 + + :param type: The type of this GpuConfig. # noqa: E501 + :type: str + """ + + self._type = type + + @property + def count(self): + """Gets the count of this GpuConfig. # noqa: E501 + + Number of GPUs requested # noqa: E501 + + :return: The count of this GpuConfig. # noqa: E501 + :rtype: int + """ + return self._count + + @count.setter + def count(self, count): + """Sets the count of this GpuConfig. + + Number of GPUs requested # noqa: E501 + + :param count: The count of this GpuConfig. # noqa: E501 + :type: int + """ + + self._count = count + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(GpuConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, GpuConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/ingress_service.py b/examples/demo9/python/mecapp/swagger_client/models/ingress_service.py new file mode 100644 index 000000000..c4ae67fa2 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/ingress_service.py @@ -0,0 +1,196 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class IngressService(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'name': 'str', + 'port': 'int', + 'external_port': 'int', + 'protocol': 'str' + } + + attribute_map = { + 'name': 'name', + 'port': 'port', + 'external_port': 'externalPort', + 'protocol': 'protocol' + } + + def __init__(self, name=None, port=None, external_port=None, protocol=None): # noqa: E501 + """IngressService - a model defined in Swagger""" # noqa: E501 + self._name = None + self._port = None + self._external_port = None + self._protocol = None + self.discriminator = None + if name is not None: + self.name = name + if port is not None: + self.port = port + if external_port is not None: + self.external_port = external_port + if protocol is not None: + self.protocol = protocol + + @property + def name(self): + """Gets the name of this IngressService. # noqa: E501 + + Service name (unique or multi-edge) # noqa: E501 + + :return: The name of this IngressService. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this IngressService. + + Service name (unique or multi-edge) # noqa: E501 + + :param name: The name of this IngressService. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def port(self): + """Gets the port of this IngressService. # noqa: E501 + + Internal service port number # noqa: E501 + + :return: The port of this IngressService. # noqa: E501 + :rtype: int + """ + return self._port + + @port.setter + def port(self, port): + """Sets the port of this IngressService. + + Internal service port number # noqa: E501 + + :param port: The port of this IngressService. # noqa: E501 + :type: int + """ + + self._port = port + + @property + def external_port(self): + """Gets the external_port of this IngressService. # noqa: E501 + + Externally-exposed unique service port in range (30000 - 32767) # noqa: E501 + + :return: The external_port of this IngressService. # noqa: E501 + :rtype: int + """ + return self._external_port + + @external_port.setter + def external_port(self, external_port): + """Sets the external_port of this IngressService. + + Externally-exposed unique service port in range (30000 - 32767) # noqa: E501 + + :param external_port: The external_port of this IngressService. # noqa: E501 + :type: int + """ + + self._external_port = external_port + + @property + def protocol(self): + """Gets the protocol of this IngressService. # noqa: E501 + + Service protocol (TCP or UDP) # noqa: E501 + + :return: The protocol of this IngressService. # noqa: E501 + :rtype: str + """ + return self._protocol + + @protocol.setter + def protocol(self, protocol): + """Sets the protocol of this IngressService. + + Service protocol (TCP or UDP) # noqa: E501 + + :param protocol: The protocol of this IngressService. # noqa: E501 + :type: str + """ + + self._protocol = protocol + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(IngressService, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, IngressService): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/line_string.py b/examples/demo9/python/mecapp/swagger_client/models/line_string.py new file mode 100644 index 000000000..980a97512 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/line_string.py @@ -0,0 +1,147 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class LineString(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'type': 'str', + 'coordinates': 'list[list[float]]' + } + + attribute_map = { + 'type': 'type', + 'coordinates': 'coordinates' + } + + def __init__(self, type=None, coordinates=None): # noqa: E501 + """LineString - a model defined in Swagger""" # noqa: E501 + self._type = None + self._coordinates = None + self.discriminator = None + self.type = type + if coordinates is not None: + self.coordinates = coordinates + + @property + def type(self): + """Gets the type of this LineString. # noqa: E501 + + Must be LineString # noqa: E501 + + :return: The type of this LineString. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this LineString. + + Must be LineString # noqa: E501 + + :param type: The type of this LineString. # noqa: E501 + :type: str + """ + if type is None: + raise ValueError("Invalid value for `type`, must not be `None`") # noqa: E501 + allowed_values = ["LineString"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def coordinates(self): + """Gets the coordinates of this LineString. # noqa: E501 + + For a LineString, coordinates is an array of two or more positions; a position is an array of two decimal numbers (longitude and latitude precisely in that order) # noqa: E501 + + :return: The coordinates of this LineString. # noqa: E501 + :rtype: list[list[float]] + """ + return self._coordinates + + @coordinates.setter + def coordinates(self, coordinates): + """Sets the coordinates of this LineString. + + For a LineString, coordinates is an array of two or more positions; a position is an array of two decimal numbers (longitude and latitude precisely in that order) # noqa: E501 + + :param coordinates: The coordinates of this LineString. # noqa: E501 + :type: list[list[float]] + """ + + self._coordinates = coordinates + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(LineString, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, LineString): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/memory_config.py b/examples/demo9/python/mecapp/swagger_client/models/memory_config.py new file mode 100644 index 000000000..12f6b1030 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/memory_config.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class MemoryConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'min': 'int', + 'max': 'int' + } + + attribute_map = { + 'min': 'min', + 'max': 'max' + } + + def __init__(self, min=None, max=None): # noqa: E501 + """MemoryConfig - a model defined in Swagger""" # noqa: E501 + self._min = None + self._max = None + self.discriminator = None + if min is not None: + self.min = min + if max is not None: + self.max = max + + @property + def min(self): + """Gets the min of this MemoryConfig. # noqa: E501 + + Minimum requested memory # noqa: E501 + + :return: The min of this MemoryConfig. # noqa: E501 + :rtype: int + """ + return self._min + + @min.setter + def min(self, min): + """Sets the min of this MemoryConfig. + + Minimum requested memory # noqa: E501 + + :param min: The min of this MemoryConfig. # noqa: E501 + :type: int + """ + + self._min = min + + @property + def max(self): + """Gets the max of this MemoryConfig. # noqa: E501 + + Maximum requested memory # noqa: E501 + + :return: The max of this MemoryConfig. # noqa: E501 + :rtype: int + """ + return self._max + + @max.setter + def max(self, max): + """Sets the max of this MemoryConfig. + + Maximum requested memory # noqa: E501 + + :param max: The max of this MemoryConfig. # noqa: E501 + :type: int + """ + + self._max = max + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(MemoryConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, MemoryConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/namespace.py b/examples/demo9/python/mecapp/swagger_client/models/namespace.py new file mode 100644 index 000000000..567e5c11f --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/namespace.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Namespace(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'sandbox_name': 'str' + } + + attribute_map = { + 'sandbox_name': 'sandbox_name' + } + + def __init__(self, sandbox_name=None): # noqa: E501 + """Namespace - a model defined in Swagger""" # noqa: E501 + self._sandbox_name = None + self.discriminator = None + if sandbox_name is not None: + self.sandbox_name = sandbox_name + + @property + def sandbox_name(self): + """Gets the sandbox_name of this Namespace. # noqa: E501 + + Name of the Sandbox # noqa: E501 + + :return: The sandbox_name of this Namespace. # noqa: E501 + :rtype: str + """ + return self._sandbox_name + + @sandbox_name.setter + def sandbox_name(self, sandbox_name): + """Sets the sandbox_name of this Namespace. + + Name of the Sandbox # noqa: E501 + + :param sandbox_name: The sandbox_name of this Namespace. # noqa: E501 + :type: str + """ + + self._sandbox_name = sandbox_name + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Namespace, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Namespace): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/network_characteristics.py b/examples/demo9/python/mecapp/swagger_client/models/network_characteristics.py new file mode 100644 index 000000000..52f57271f --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/network_characteristics.py @@ -0,0 +1,286 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class NetworkCharacteristics(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'latency': 'int', + 'latency_variation': 'int', + 'latency_distribution': 'str', + 'throughput': 'int', + 'throughput_dl': 'int', + 'throughput_ul': 'int', + 'packet_loss': 'float' + } + + attribute_map = { + 'latency': 'latency', + 'latency_variation': 'latencyVariation', + 'latency_distribution': 'latencyDistribution', + 'throughput': 'throughput', + 'throughput_dl': 'throughputDl', + 'throughput_ul': 'throughputUl', + 'packet_loss': 'packetLoss' + } + + def __init__(self, latency=None, latency_variation=None, latency_distribution=None, throughput=None, throughput_dl=None, throughput_ul=None, packet_loss=None): # noqa: E501 + """NetworkCharacteristics - a model defined in Swagger""" # noqa: E501 + self._latency = None + self._latency_variation = None + self._latency_distribution = None + self._throughput = None + self._throughput_dl = None + self._throughput_ul = None + self._packet_loss = None + self.discriminator = None + if latency is not None: + self.latency = latency + if latency_variation is not None: + self.latency_variation = latency_variation + if latency_distribution is not None: + self.latency_distribution = latency_distribution + if throughput is not None: + self.throughput = throughput + if throughput_dl is not None: + self.throughput_dl = throughput_dl + if throughput_ul is not None: + self.throughput_ul = throughput_ul + if packet_loss is not None: + self.packet_loss = packet_loss + + @property + def latency(self): + """Gets the latency of this NetworkCharacteristics. # noqa: E501 + + Latency in ms # noqa: E501 + + :return: The latency of this NetworkCharacteristics. # noqa: E501 + :rtype: int + """ + return self._latency + + @latency.setter + def latency(self, latency): + """Sets the latency of this NetworkCharacteristics. + + Latency in ms # noqa: E501 + + :param latency: The latency of this NetworkCharacteristics. # noqa: E501 + :type: int + """ + + self._latency = latency + + @property + def latency_variation(self): + """Gets the latency_variation of this NetworkCharacteristics. # noqa: E501 + + Latency variation in ms # noqa: E501 + + :return: The latency_variation of this NetworkCharacteristics. # noqa: E501 + :rtype: int + """ + return self._latency_variation + + @latency_variation.setter + def latency_variation(self, latency_variation): + """Sets the latency_variation of this NetworkCharacteristics. + + Latency variation in ms # noqa: E501 + + :param latency_variation: The latency_variation of this NetworkCharacteristics. # noqa: E501 + :type: int + """ + + self._latency_variation = latency_variation + + @property + def latency_distribution(self): + """Gets the latency_distribution of this NetworkCharacteristics. # noqa: E501 + + Latency distribution. Can only be set in the Scenario Deployment network characteristics, ignored otherwise. Latency distribution is set for the whole network and applied to every end-to-end traffic flows. Default value is 'Normal' distribution. # noqa: E501 + + :return: The latency_distribution of this NetworkCharacteristics. # noqa: E501 + :rtype: str + """ + return self._latency_distribution + + @latency_distribution.setter + def latency_distribution(self, latency_distribution): + """Sets the latency_distribution of this NetworkCharacteristics. + + Latency distribution. Can only be set in the Scenario Deployment network characteristics, ignored otherwise. Latency distribution is set for the whole network and applied to every end-to-end traffic flows. Default value is 'Normal' distribution. # noqa: E501 + + :param latency_distribution: The latency_distribution of this NetworkCharacteristics. # noqa: E501 + :type: str + """ + allowed_values = ["Normal", "Pareto", "Paretonormal", "Uniform"] # noqa: E501 + if latency_distribution not in allowed_values: + raise ValueError( + "Invalid value for `latency_distribution` ({0}), must be one of {1}" # noqa: E501 + .format(latency_distribution, allowed_values) + ) + + self._latency_distribution = latency_distribution + + @property + def throughput(self): + """Gets the throughput of this NetworkCharacteristics. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by throughputUl and throughputDl # noqa: E501 + + :return: The throughput of this NetworkCharacteristics. # noqa: E501 + :rtype: int + """ + return self._throughput + + @throughput.setter + def throughput(self, throughput): + """Sets the throughput of this NetworkCharacteristics. + + **DEPRECATED** As of release 1.5.0, replaced by throughputUl and throughputDl # noqa: E501 + + :param throughput: The throughput of this NetworkCharacteristics. # noqa: E501 + :type: int + """ + + self._throughput = throughput + + @property + def throughput_dl(self): + """Gets the throughput_dl of this NetworkCharacteristics. # noqa: E501 + + Downlink throughput limit in Mbps # noqa: E501 + + :return: The throughput_dl of this NetworkCharacteristics. # noqa: E501 + :rtype: int + """ + return self._throughput_dl + + @throughput_dl.setter + def throughput_dl(self, throughput_dl): + """Sets the throughput_dl of this NetworkCharacteristics. + + Downlink throughput limit in Mbps # noqa: E501 + + :param throughput_dl: The throughput_dl of this NetworkCharacteristics. # noqa: E501 + :type: int + """ + + self._throughput_dl = throughput_dl + + @property + def throughput_ul(self): + """Gets the throughput_ul of this NetworkCharacteristics. # noqa: E501 + + Uplink throughput limit in Mbps # noqa: E501 + + :return: The throughput_ul of this NetworkCharacteristics. # noqa: E501 + :rtype: int + """ + return self._throughput_ul + + @throughput_ul.setter + def throughput_ul(self, throughput_ul): + """Sets the throughput_ul of this NetworkCharacteristics. + + Uplink throughput limit in Mbps # noqa: E501 + + :param throughput_ul: The throughput_ul of this NetworkCharacteristics. # noqa: E501 + :type: int + """ + + self._throughput_ul = throughput_ul + + @property + def packet_loss(self): + """Gets the packet_loss of this NetworkCharacteristics. # noqa: E501 + + Packet loss percentage # noqa: E501 + + :return: The packet_loss of this NetworkCharacteristics. # noqa: E501 + :rtype: float + """ + return self._packet_loss + + @packet_loss.setter + def packet_loss(self, packet_loss): + """Sets the packet_loss of this NetworkCharacteristics. + + Packet loss percentage # noqa: E501 + + :param packet_loss: The packet_loss of this NetworkCharacteristics. # noqa: E501 + :type: float + """ + + self._packet_loss = packet_loss + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(NetworkCharacteristics, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, NetworkCharacteristics): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/network_location.py b/examples/demo9/python/mecapp/swagger_client/models/network_location.py new file mode 100644 index 000000000..0fc0a0038 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/network_location.py @@ -0,0 +1,524 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class NetworkLocation(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'name': 'str', + 'type': 'str', + 'net_char': 'NetworkCharacteristics', + 'terminal_link_latency': 'int', + 'terminal_link_latency_variation': 'int', + 'terminal_link_throughput': 'int', + 'terminal_link_packet_loss': 'float', + 'meta': 'dict(str, str)', + 'user_meta': 'dict(str, str)', + 'cellular_poa_config': 'CellularPoaConfig', + 'poa4_g_config': 'Poa4GConfig', + 'poa5_g_config': 'Poa5GConfig', + 'poa_wifi_config': 'PoaWifiConfig', + 'geo_data': 'GeoData', + 'physical_locations': 'list[PhysicalLocation]' + } + + attribute_map = { + 'id': 'id', + 'name': 'name', + 'type': 'type', + 'net_char': 'netChar', + 'terminal_link_latency': 'terminalLinkLatency', + 'terminal_link_latency_variation': 'terminalLinkLatencyVariation', + 'terminal_link_throughput': 'terminalLinkThroughput', + 'terminal_link_packet_loss': 'terminalLinkPacketLoss', + 'meta': 'meta', + 'user_meta': 'userMeta', + 'cellular_poa_config': 'cellularPoaConfig', + 'poa4_g_config': 'poa4GConfig', + 'poa5_g_config': 'poa5GConfig', + 'poa_wifi_config': 'poaWifiConfig', + 'geo_data': 'geoData', + 'physical_locations': 'physicalLocations' + } + + def __init__(self, id=None, name=None, type=None, net_char=None, terminal_link_latency=None, terminal_link_latency_variation=None, terminal_link_throughput=None, terminal_link_packet_loss=None, meta=None, user_meta=None, cellular_poa_config=None, poa4_g_config=None, poa5_g_config=None, poa_wifi_config=None, geo_data=None, physical_locations=None): # noqa: E501 + """NetworkLocation - a model defined in Swagger""" # noqa: E501 + self._id = None + self._name = None + self._type = None + self._net_char = None + self._terminal_link_latency = None + self._terminal_link_latency_variation = None + self._terminal_link_throughput = None + self._terminal_link_packet_loss = None + self._meta = None + self._user_meta = None + self._cellular_poa_config = None + self._poa4_g_config = None + self._poa5_g_config = None + self._poa_wifi_config = None + self._geo_data = None + self._physical_locations = None + self.discriminator = None + if id is not None: + self.id = id + if name is not None: + self.name = name + if type is not None: + self.type = type + if net_char is not None: + self.net_char = net_char + if terminal_link_latency is not None: + self.terminal_link_latency = terminal_link_latency + if terminal_link_latency_variation is not None: + self.terminal_link_latency_variation = terminal_link_latency_variation + if terminal_link_throughput is not None: + self.terminal_link_throughput = terminal_link_throughput + if terminal_link_packet_loss is not None: + self.terminal_link_packet_loss = terminal_link_packet_loss + if meta is not None: + self.meta = meta + if user_meta is not None: + self.user_meta = user_meta + if cellular_poa_config is not None: + self.cellular_poa_config = cellular_poa_config + if poa4_g_config is not None: + self.poa4_g_config = poa4_g_config + if poa5_g_config is not None: + self.poa5_g_config = poa5_g_config + if poa_wifi_config is not None: + self.poa_wifi_config = poa_wifi_config + if geo_data is not None: + self.geo_data = geo_data + if physical_locations is not None: + self.physical_locations = physical_locations + + @property + def id(self): + """Gets the id of this NetworkLocation. # noqa: E501 + + Unique network location ID # noqa: E501 + + :return: The id of this NetworkLocation. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this NetworkLocation. + + Unique network location ID # noqa: E501 + + :param id: The id of this NetworkLocation. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this NetworkLocation. # noqa: E501 + + Network location name # noqa: E501 + + :return: The name of this NetworkLocation. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this NetworkLocation. + + Network location name # noqa: E501 + + :param name: The name of this NetworkLocation. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def type(self): + """Gets the type of this NetworkLocation. # noqa: E501 + + Network location type # noqa: E501 + + :return: The type of this NetworkLocation. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this NetworkLocation. + + Network location type # noqa: E501 + + :param type: The type of this NetworkLocation. # noqa: E501 + :type: str + """ + allowed_values = ["POA", "POA-4G", "POA-5G", "POA-WIFI", "DEFAULT"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def net_char(self): + """Gets the net_char of this NetworkLocation. # noqa: E501 + + + :return: The net_char of this NetworkLocation. # noqa: E501 + :rtype: NetworkCharacteristics + """ + return self._net_char + + @net_char.setter + def net_char(self, net_char): + """Sets the net_char of this NetworkLocation. + + + :param net_char: The net_char of this NetworkLocation. # noqa: E501 + :type: NetworkCharacteristics + """ + + self._net_char = net_char + + @property + def terminal_link_latency(self): + """Gets the terminal_link_latency of this NetworkLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :return: The terminal_link_latency of this NetworkLocation. # noqa: E501 + :rtype: int + """ + return self._terminal_link_latency + + @terminal_link_latency.setter + def terminal_link_latency(self, terminal_link_latency): + """Sets the terminal_link_latency of this NetworkLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :param terminal_link_latency: The terminal_link_latency of this NetworkLocation. # noqa: E501 + :type: int + """ + + self._terminal_link_latency = terminal_link_latency + + @property + def terminal_link_latency_variation(self): + """Gets the terminal_link_latency_variation of this NetworkLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :return: The terminal_link_latency_variation of this NetworkLocation. # noqa: E501 + :rtype: int + """ + return self._terminal_link_latency_variation + + @terminal_link_latency_variation.setter + def terminal_link_latency_variation(self, terminal_link_latency_variation): + """Sets the terminal_link_latency_variation of this NetworkLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :param terminal_link_latency_variation: The terminal_link_latency_variation of this NetworkLocation. # noqa: E501 + :type: int + """ + + self._terminal_link_latency_variation = terminal_link_latency_variation + + @property + def terminal_link_throughput(self): + """Gets the terminal_link_throughput of this NetworkLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :return: The terminal_link_throughput of this NetworkLocation. # noqa: E501 + :rtype: int + """ + return self._terminal_link_throughput + + @terminal_link_throughput.setter + def terminal_link_throughput(self, terminal_link_throughput): + """Sets the terminal_link_throughput of this NetworkLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :param terminal_link_throughput: The terminal_link_throughput of this NetworkLocation. # noqa: E501 + :type: int + """ + + self._terminal_link_throughput = terminal_link_throughput + + @property + def terminal_link_packet_loss(self): + """Gets the terminal_link_packet_loss of this NetworkLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :return: The terminal_link_packet_loss of this NetworkLocation. # noqa: E501 + :rtype: float + """ + return self._terminal_link_packet_loss + + @terminal_link_packet_loss.setter + def terminal_link_packet_loss(self, terminal_link_packet_loss): + """Sets the terminal_link_packet_loss of this NetworkLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :param terminal_link_packet_loss: The terminal_link_packet_loss of this NetworkLocation. # noqa: E501 + :type: float + """ + + self._terminal_link_packet_loss = terminal_link_packet_loss + + @property + def meta(self): + """Gets the meta of this NetworkLocation. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The meta of this NetworkLocation. # noqa: E501 + :rtype: dict(str, str) + """ + return self._meta + + @meta.setter + def meta(self, meta): + """Sets the meta of this NetworkLocation. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param meta: The meta of this NetworkLocation. # noqa: E501 + :type: dict(str, str) + """ + + self._meta = meta + + @property + def user_meta(self): + """Gets the user_meta of this NetworkLocation. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The user_meta of this NetworkLocation. # noqa: E501 + :rtype: dict(str, str) + """ + return self._user_meta + + @user_meta.setter + def user_meta(self, user_meta): + """Sets the user_meta of this NetworkLocation. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param user_meta: The user_meta of this NetworkLocation. # noqa: E501 + :type: dict(str, str) + """ + + self._user_meta = user_meta + + @property + def cellular_poa_config(self): + """Gets the cellular_poa_config of this NetworkLocation. # noqa: E501 + + + :return: The cellular_poa_config of this NetworkLocation. # noqa: E501 + :rtype: CellularPoaConfig + """ + return self._cellular_poa_config + + @cellular_poa_config.setter + def cellular_poa_config(self, cellular_poa_config): + """Sets the cellular_poa_config of this NetworkLocation. + + + :param cellular_poa_config: The cellular_poa_config of this NetworkLocation. # noqa: E501 + :type: CellularPoaConfig + """ + + self._cellular_poa_config = cellular_poa_config + + @property + def poa4_g_config(self): + """Gets the poa4_g_config of this NetworkLocation. # noqa: E501 + + + :return: The poa4_g_config of this NetworkLocation. # noqa: E501 + :rtype: Poa4GConfig + """ + return self._poa4_g_config + + @poa4_g_config.setter + def poa4_g_config(self, poa4_g_config): + """Sets the poa4_g_config of this NetworkLocation. + + + :param poa4_g_config: The poa4_g_config of this NetworkLocation. # noqa: E501 + :type: Poa4GConfig + """ + + self._poa4_g_config = poa4_g_config + + @property + def poa5_g_config(self): + """Gets the poa5_g_config of this NetworkLocation. # noqa: E501 + + + :return: The poa5_g_config of this NetworkLocation. # noqa: E501 + :rtype: Poa5GConfig + """ + return self._poa5_g_config + + @poa5_g_config.setter + def poa5_g_config(self, poa5_g_config): + """Sets the poa5_g_config of this NetworkLocation. + + + :param poa5_g_config: The poa5_g_config of this NetworkLocation. # noqa: E501 + :type: Poa5GConfig + """ + + self._poa5_g_config = poa5_g_config + + @property + def poa_wifi_config(self): + """Gets the poa_wifi_config of this NetworkLocation. # noqa: E501 + + + :return: The poa_wifi_config of this NetworkLocation. # noqa: E501 + :rtype: PoaWifiConfig + """ + return self._poa_wifi_config + + @poa_wifi_config.setter + def poa_wifi_config(self, poa_wifi_config): + """Sets the poa_wifi_config of this NetworkLocation. + + + :param poa_wifi_config: The poa_wifi_config of this NetworkLocation. # noqa: E501 + :type: PoaWifiConfig + """ + + self._poa_wifi_config = poa_wifi_config + + @property + def geo_data(self): + """Gets the geo_data of this NetworkLocation. # noqa: E501 + + + :return: The geo_data of this NetworkLocation. # noqa: E501 + :rtype: GeoData + """ + return self._geo_data + + @geo_data.setter + def geo_data(self, geo_data): + """Sets the geo_data of this NetworkLocation. + + + :param geo_data: The geo_data of this NetworkLocation. # noqa: E501 + :type: GeoData + """ + + self._geo_data = geo_data + + @property + def physical_locations(self): + """Gets the physical_locations of this NetworkLocation. # noqa: E501 + + + :return: The physical_locations of this NetworkLocation. # noqa: E501 + :rtype: list[PhysicalLocation] + """ + return self._physical_locations + + @physical_locations.setter + def physical_locations(self, physical_locations): + """Sets the physical_locations of this NetworkLocation. + + + :param physical_locations: The physical_locations of this NetworkLocation. # noqa: E501 + :type: list[PhysicalLocation] + """ + + self._physical_locations = physical_locations + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(NetworkLocation, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, NetworkLocation): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/oauth.py b/examples/demo9/python/mecapp/swagger_client/models/oauth.py new file mode 100644 index 000000000..158067aae --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/oauth.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Oauth(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'user_code': 'str', + 'verification_uri': 'str' + } + + attribute_map = { + 'user_code': 'user_code', + 'verification_uri': 'verification_uri' + } + + def __init__(self, user_code=None, verification_uri=None): # noqa: E501 + """Oauth - a model defined in Swagger""" # noqa: E501 + self._user_code = None + self._verification_uri = None + self.discriminator = None + if user_code is not None: + self.user_code = user_code + if verification_uri is not None: + self.verification_uri = verification_uri + + @property + def user_code(self): + """Gets the user_code of this Oauth. # noqa: E501 + + User code from the authentication provider # noqa: E501 + + :return: The user_code of this Oauth. # noqa: E501 + :rtype: str + """ + return self._user_code + + @user_code.setter + def user_code(self, user_code): + """Sets the user_code of this Oauth. + + User code from the authentication provider # noqa: E501 + + :param user_code: The user_code of this Oauth. # noqa: E501 + :type: str + """ + + self._user_code = user_code + + @property + def verification_uri(self): + """Gets the verification_uri of this Oauth. # noqa: E501 + + Verification URI to go to and enter the user code in order to authenticate # noqa: E501 + + :return: The verification_uri of this Oauth. # noqa: E501 + :rtype: str + """ + return self._verification_uri + + @verification_uri.setter + def verification_uri(self, verification_uri): + """Sets the verification_uri of this Oauth. + + Verification URI to go to and enter the user code in order to authenticate # noqa: E501 + + :param verification_uri: The verification_uri of this Oauth. # noqa: E501 + :type: str + """ + + self._verification_uri = verification_uri + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Oauth, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Oauth): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/physical_location.py b/examples/demo9/python/mecapp/swagger_client/models/physical_location.py new file mode 100644 index 000000000..586d05005 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/physical_location.py @@ -0,0 +1,612 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class PhysicalLocation(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'name': 'str', + 'type': 'str', + 'is_external': 'bool', + 'geo_data': 'GeoData', + 'network_locations_in_range': 'list[str]', + 'connected': 'bool', + 'wireless': 'bool', + 'wireless_type': 'str', + 'data_network': 'DNConfig', + 'meta': 'dict(str, str)', + 'user_meta': 'dict(str, str)', + 'processes': 'list[Process]', + 'net_char': 'NetworkCharacteristics', + 'link_latency': 'int', + 'link_latency_variation': 'int', + 'link_throughput': 'int', + 'link_packet_loss': 'float', + 'mac_id': 'str' + } + + attribute_map = { + 'id': 'id', + 'name': 'name', + 'type': 'type', + 'is_external': 'isExternal', + 'geo_data': 'geoData', + 'network_locations_in_range': 'networkLocationsInRange', + 'connected': 'connected', + 'wireless': 'wireless', + 'wireless_type': 'wirelessType', + 'data_network': 'dataNetwork', + 'meta': 'meta', + 'user_meta': 'userMeta', + 'processes': 'processes', + 'net_char': 'netChar', + 'link_latency': 'linkLatency', + 'link_latency_variation': 'linkLatencyVariation', + 'link_throughput': 'linkThroughput', + 'link_packet_loss': 'linkPacketLoss', + 'mac_id': 'macId' + } + + def __init__(self, id=None, name=None, type=None, is_external=None, geo_data=None, network_locations_in_range=None, connected=None, wireless=None, wireless_type=None, data_network=None, meta=None, user_meta=None, processes=None, net_char=None, link_latency=None, link_latency_variation=None, link_throughput=None, link_packet_loss=None, mac_id=None): # noqa: E501 + """PhysicalLocation - a model defined in Swagger""" # noqa: E501 + self._id = None + self._name = None + self._type = None + self._is_external = None + self._geo_data = None + self._network_locations_in_range = None + self._connected = None + self._wireless = None + self._wireless_type = None + self._data_network = None + self._meta = None + self._user_meta = None + self._processes = None + self._net_char = None + self._link_latency = None + self._link_latency_variation = None + self._link_throughput = None + self._link_packet_loss = None + self._mac_id = None + self.discriminator = None + if id is not None: + self.id = id + if name is not None: + self.name = name + if type is not None: + self.type = type + if is_external is not None: + self.is_external = is_external + if geo_data is not None: + self.geo_data = geo_data + if network_locations_in_range is not None: + self.network_locations_in_range = network_locations_in_range + if connected is not None: + self.connected = connected + if wireless is not None: + self.wireless = wireless + if wireless_type is not None: + self.wireless_type = wireless_type + if data_network is not None: + self.data_network = data_network + if meta is not None: + self.meta = meta + if user_meta is not None: + self.user_meta = user_meta + if processes is not None: + self.processes = processes + if net_char is not None: + self.net_char = net_char + if link_latency is not None: + self.link_latency = link_latency + if link_latency_variation is not None: + self.link_latency_variation = link_latency_variation + if link_throughput is not None: + self.link_throughput = link_throughput + if link_packet_loss is not None: + self.link_packet_loss = link_packet_loss + if mac_id is not None: + self.mac_id = mac_id + + @property + def id(self): + """Gets the id of this PhysicalLocation. # noqa: E501 + + Unique physical location ID # noqa: E501 + + :return: The id of this PhysicalLocation. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this PhysicalLocation. + + Unique physical location ID # noqa: E501 + + :param id: The id of this PhysicalLocation. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this PhysicalLocation. # noqa: E501 + + Physical location name # noqa: E501 + + :return: The name of this PhysicalLocation. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this PhysicalLocation. + + Physical location name # noqa: E501 + + :param name: The name of this PhysicalLocation. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def type(self): + """Gets the type of this PhysicalLocation. # noqa: E501 + + Physical location type # noqa: E501 + + :return: The type of this PhysicalLocation. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this PhysicalLocation. + + Physical location type # noqa: E501 + + :param type: The type of this PhysicalLocation. # noqa: E501 + :type: str + """ + allowed_values = ["UE", "FOG", "EDGE", "CN", "DC"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def is_external(self): + """Gets the is_external of this PhysicalLocation. # noqa: E501 + + true: Physical location is external to MEEP false: Physical location is internal to MEEP # noqa: E501 + + :return: The is_external of this PhysicalLocation. # noqa: E501 + :rtype: bool + """ + return self._is_external + + @is_external.setter + def is_external(self, is_external): + """Sets the is_external of this PhysicalLocation. + + true: Physical location is external to MEEP false: Physical location is internal to MEEP # noqa: E501 + + :param is_external: The is_external of this PhysicalLocation. # noqa: E501 + :type: bool + """ + + self._is_external = is_external + + @property + def geo_data(self): + """Gets the geo_data of this PhysicalLocation. # noqa: E501 + + + :return: The geo_data of this PhysicalLocation. # noqa: E501 + :rtype: GeoData + """ + return self._geo_data + + @geo_data.setter + def geo_data(self, geo_data): + """Sets the geo_data of this PhysicalLocation. + + + :param geo_data: The geo_data of this PhysicalLocation. # noqa: E501 + :type: GeoData + """ + + self._geo_data = geo_data + + @property + def network_locations_in_range(self): + """Gets the network_locations_in_range of this PhysicalLocation. # noqa: E501 + + + :return: The network_locations_in_range of this PhysicalLocation. # noqa: E501 + :rtype: list[str] + """ + return self._network_locations_in_range + + @network_locations_in_range.setter + def network_locations_in_range(self, network_locations_in_range): + """Sets the network_locations_in_range of this PhysicalLocation. + + + :param network_locations_in_range: The network_locations_in_range of this PhysicalLocation. # noqa: E501 + :type: list[str] + """ + + self._network_locations_in_range = network_locations_in_range + + @property + def connected(self): + """Gets the connected of this PhysicalLocation. # noqa: E501 + + true: Physical location has network connectivity false: Physical location has no network connectivity # noqa: E501 + + :return: The connected of this PhysicalLocation. # noqa: E501 + :rtype: bool + """ + return self._connected + + @connected.setter + def connected(self, connected): + """Sets the connected of this PhysicalLocation. + + true: Physical location has network connectivity false: Physical location has no network connectivity # noqa: E501 + + :param connected: The connected of this PhysicalLocation. # noqa: E501 + :type: bool + """ + + self._connected = connected + + @property + def wireless(self): + """Gets the wireless of this PhysicalLocation. # noqa: E501 + + true: Physical location uses a wireless connection false: Physical location uses a wired connection # noqa: E501 + + :return: The wireless of this PhysicalLocation. # noqa: E501 + :rtype: bool + """ + return self._wireless + + @wireless.setter + def wireless(self, wireless): + """Sets the wireless of this PhysicalLocation. + + true: Physical location uses a wireless connection false: Physical location uses a wired connection # noqa: E501 + + :param wireless: The wireless of this PhysicalLocation. # noqa: E501 + :type: bool + """ + + self._wireless = wireless + + @property + def wireless_type(self): + """Gets the wireless_type of this PhysicalLocation. # noqa: E501 + + Prioritized, comma-separated list of supported wireless connection types. Default priority if not specififed is 'wifi,5g,4g,other'. Wireless connection types: - 4g - 5g - wifi - other # noqa: E501 + + :return: The wireless_type of this PhysicalLocation. # noqa: E501 + :rtype: str + """ + return self._wireless_type + + @wireless_type.setter + def wireless_type(self, wireless_type): + """Sets the wireless_type of this PhysicalLocation. + + Prioritized, comma-separated list of supported wireless connection types. Default priority if not specififed is 'wifi,5g,4g,other'. Wireless connection types: - 4g - 5g - wifi - other # noqa: E501 + + :param wireless_type: The wireless_type of this PhysicalLocation. # noqa: E501 + :type: str + """ + + self._wireless_type = wireless_type + + @property + def data_network(self): + """Gets the data_network of this PhysicalLocation. # noqa: E501 + + + :return: The data_network of this PhysicalLocation. # noqa: E501 + :rtype: DNConfig + """ + return self._data_network + + @data_network.setter + def data_network(self, data_network): + """Sets the data_network of this PhysicalLocation. + + + :param data_network: The data_network of this PhysicalLocation. # noqa: E501 + :type: DNConfig + """ + + self._data_network = data_network + + @property + def meta(self): + """Gets the meta of this PhysicalLocation. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The meta of this PhysicalLocation. # noqa: E501 + :rtype: dict(str, str) + """ + return self._meta + + @meta.setter + def meta(self, meta): + """Sets the meta of this PhysicalLocation. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param meta: The meta of this PhysicalLocation. # noqa: E501 + :type: dict(str, str) + """ + + self._meta = meta + + @property + def user_meta(self): + """Gets the user_meta of this PhysicalLocation. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The user_meta of this PhysicalLocation. # noqa: E501 + :rtype: dict(str, str) + """ + return self._user_meta + + @user_meta.setter + def user_meta(self, user_meta): + """Sets the user_meta of this PhysicalLocation. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param user_meta: The user_meta of this PhysicalLocation. # noqa: E501 + :type: dict(str, str) + """ + + self._user_meta = user_meta + + @property + def processes(self): + """Gets the processes of this PhysicalLocation. # noqa: E501 + + + :return: The processes of this PhysicalLocation. # noqa: E501 + :rtype: list[Process] + """ + return self._processes + + @processes.setter + def processes(self, processes): + """Sets the processes of this PhysicalLocation. + + + :param processes: The processes of this PhysicalLocation. # noqa: E501 + :type: list[Process] + """ + + self._processes = processes + + @property + def net_char(self): + """Gets the net_char of this PhysicalLocation. # noqa: E501 + + + :return: The net_char of this PhysicalLocation. # noqa: E501 + :rtype: NetworkCharacteristics + """ + return self._net_char + + @net_char.setter + def net_char(self, net_char): + """Sets the net_char of this PhysicalLocation. + + + :param net_char: The net_char of this PhysicalLocation. # noqa: E501 + :type: NetworkCharacteristics + """ + + self._net_char = net_char + + @property + def link_latency(self): + """Gets the link_latency of this PhysicalLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :return: The link_latency of this PhysicalLocation. # noqa: E501 + :rtype: int + """ + return self._link_latency + + @link_latency.setter + def link_latency(self, link_latency): + """Sets the link_latency of this PhysicalLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :param link_latency: The link_latency of this PhysicalLocation. # noqa: E501 + :type: int + """ + + self._link_latency = link_latency + + @property + def link_latency_variation(self): + """Gets the link_latency_variation of this PhysicalLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :return: The link_latency_variation of this PhysicalLocation. # noqa: E501 + :rtype: int + """ + return self._link_latency_variation + + @link_latency_variation.setter + def link_latency_variation(self, link_latency_variation): + """Sets the link_latency_variation of this PhysicalLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :param link_latency_variation: The link_latency_variation of this PhysicalLocation. # noqa: E501 + :type: int + """ + + self._link_latency_variation = link_latency_variation + + @property + def link_throughput(self): + """Gets the link_throughput of this PhysicalLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :return: The link_throughput of this PhysicalLocation. # noqa: E501 + :rtype: int + """ + return self._link_throughput + + @link_throughput.setter + def link_throughput(self, link_throughput): + """Sets the link_throughput of this PhysicalLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :param link_throughput: The link_throughput of this PhysicalLocation. # noqa: E501 + :type: int + """ + + self._link_throughput = link_throughput + + @property + def link_packet_loss(self): + """Gets the link_packet_loss of this PhysicalLocation. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :return: The link_packet_loss of this PhysicalLocation. # noqa: E501 + :rtype: float + """ + return self._link_packet_loss + + @link_packet_loss.setter + def link_packet_loss(self, link_packet_loss): + """Sets the link_packet_loss of this PhysicalLocation. + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :param link_packet_loss: The link_packet_loss of this PhysicalLocation. # noqa: E501 + :type: float + """ + + self._link_packet_loss = link_packet_loss + + @property + def mac_id(self): + """Gets the mac_id of this PhysicalLocation. # noqa: E501 + + Physical location MAC Address # noqa: E501 + + :return: The mac_id of this PhysicalLocation. # noqa: E501 + :rtype: str + """ + return self._mac_id + + @mac_id.setter + def mac_id(self, mac_id): + """Sets the mac_id of this PhysicalLocation. + + Physical location MAC Address # noqa: E501 + + :param mac_id: The mac_id of this PhysicalLocation. # noqa: E501 + :type: str + """ + + self._mac_id = mac_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(PhysicalLocation, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, PhysicalLocation): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/poa4_g_config.py b/examples/demo9/python/mecapp/swagger_client/models/poa4_g_config.py new file mode 100644 index 000000000..ffacd20a2 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/poa4_g_config.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Poa4GConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'cell_id': 'str' + } + + attribute_map = { + 'cell_id': 'cellId' + } + + def __init__(self, cell_id=None): # noqa: E501 + """Poa4GConfig - a model defined in Swagger""" # noqa: E501 + self._cell_id = None + self.discriminator = None + if cell_id is not None: + self.cell_id = cell_id + + @property + def cell_id(self): + """Gets the cell_id of this Poa4GConfig. # noqa: E501 + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell # noqa: E501 + + :return: The cell_id of this Poa4GConfig. # noqa: E501 + :rtype: str + """ + return self._cell_id + + @cell_id.setter + def cell_id(self, cell_id): + """Sets the cell_id of this Poa4GConfig. + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the eNB serving the cell # noqa: E501 + + :param cell_id: The cell_id of this Poa4GConfig. # noqa: E501 + :type: str + """ + + self._cell_id = cell_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Poa4GConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Poa4GConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/poa5_g_config.py b/examples/demo9/python/mecapp/swagger_client/models/poa5_g_config.py new file mode 100644 index 000000000..441d0d777 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/poa5_g_config.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Poa5GConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'cell_id': 'str' + } + + attribute_map = { + 'cell_id': 'cellId' + } + + def __init__(self, cell_id=None): # noqa: E501 + """Poa5GConfig - a model defined in Swagger""" # noqa: E501 + self._cell_id = None + self.discriminator = None + if cell_id is not None: + self.cell_id = cell_id + + @property + def cell_id(self): + """Gets the cell_id of this Poa5GConfig. # noqa: E501 + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the NR serving the cell # noqa: E501 + + :return: The cell_id of this Poa5GConfig. # noqa: E501 + :rtype: str + """ + return self._cell_id + + @cell_id.setter + def cell_id(self, cell_id): + """Sets the cell_id of this Poa5GConfig. + + The E-UTRAN Cell Identity as defined in ETSI TS 136 413 including the ID of the NR serving the cell # noqa: E501 + + :param cell_id: The cell_id of this Poa5GConfig. # noqa: E501 + :type: str + """ + + self._cell_id = cell_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Poa5GConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Poa5GConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/poa_wifi_config.py b/examples/demo9/python/mecapp/swagger_client/models/poa_wifi_config.py new file mode 100644 index 000000000..a76662588 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/poa_wifi_config.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class PoaWifiConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'mac_id': 'str' + } + + attribute_map = { + 'mac_id': 'macId' + } + + def __init__(self, mac_id=None): # noqa: E501 + """PoaWifiConfig - a model defined in Swagger""" # noqa: E501 + self._mac_id = None + self.discriminator = None + if mac_id is not None: + self.mac_id = mac_id + + @property + def mac_id(self): + """Gets the mac_id of this PoaWifiConfig. # noqa: E501 + + WIFI POA MAC Address # noqa: E501 + + :return: The mac_id of this PoaWifiConfig. # noqa: E501 + :rtype: str + """ + return self._mac_id + + @mac_id.setter + def mac_id(self, mac_id): + """Sets the mac_id of this PoaWifiConfig. + + WIFI POA MAC Address # noqa: E501 + + :param mac_id: The mac_id of this PoaWifiConfig. # noqa: E501 + :type: str + """ + + self._mac_id = mac_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(PoaWifiConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, PoaWifiConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/point.py b/examples/demo9/python/mecapp/swagger_client/models/point.py new file mode 100644 index 000000000..c5598afd1 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/point.py @@ -0,0 +1,147 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Point(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'type': 'str', + 'coordinates': 'list[float]' + } + + attribute_map = { + 'type': 'type', + 'coordinates': 'coordinates' + } + + def __init__(self, type=None, coordinates=None): # noqa: E501 + """Point - a model defined in Swagger""" # noqa: E501 + self._type = None + self._coordinates = None + self.discriminator = None + self.type = type + if coordinates is not None: + self.coordinates = coordinates + + @property + def type(self): + """Gets the type of this Point. # noqa: E501 + + Must be Point # noqa: E501 + + :return: The type of this Point. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this Point. + + Must be Point # noqa: E501 + + :param type: The type of this Point. # noqa: E501 + :type: str + """ + if type is None: + raise ValueError("Invalid value for `type`, must not be `None`") # noqa: E501 + allowed_values = ["Point"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def coordinates(self): + """Gets the coordinates of this Point. # noqa: E501 + + For a Point, coordinates MUST be an array of two decimal numbers; longitude and latitude precisely in that order # noqa: E501 + + :return: The coordinates of this Point. # noqa: E501 + :rtype: list[float] + """ + return self._coordinates + + @coordinates.setter + def coordinates(self, coordinates): + """Sets the coordinates of this Point. + + For a Point, coordinates MUST be an array of two decimal numbers; longitude and latitude precisely in that order # noqa: E501 + + :param coordinates: The coordinates of this Point. # noqa: E501 + :type: list[float] + """ + + self._coordinates = coordinates + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Point, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Point): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/problem_details.py b/examples/demo9/python/mecapp/swagger_client/models/problem_details.py new file mode 100644 index 000000000..01f1e7387 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/problem_details.py @@ -0,0 +1,226 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ProblemDetails(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'type': 'str', + 'title': 'str', + 'status': 'int', + 'detail': 'str', + 'instance': 'str' + } + + attribute_map = { + 'type': 'type', + 'title': 'title', + 'status': 'status', + 'detail': 'detail', + 'instance': 'instance' + } + + def __init__(self, type=None, title=None, status=None, detail=None, instance=None): # noqa: E501 + """ProblemDetails - a model defined in Swagger""" # noqa: E501 + self._type = None + self._title = None + self._status = None + self._detail = None + self._instance = None + self.discriminator = None + if type is not None: + self.type = type + if title is not None: + self.title = title + self.status = status + self.detail = detail + if instance is not None: + self.instance = instance + + @property + def type(self): + """Gets the type of this ProblemDetails. # noqa: E501 + + A URI reference according to IETF RFC 3986 that identifies the problem type. It is encouraged that the URI provides human-readable documentation for the problem (e.g. using HTML) when dereferenced. When this member is not present, its value is assumed to be \"about:blank\". # noqa: E501 + + :return: The type of this ProblemDetails. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this ProblemDetails. + + A URI reference according to IETF RFC 3986 that identifies the problem type. It is encouraged that the URI provides human-readable documentation for the problem (e.g. using HTML) when dereferenced. When this member is not present, its value is assumed to be \"about:blank\". # noqa: E501 + + :param type: The type of this ProblemDetails. # noqa: E501 + :type: str + """ + + self._type = type + + @property + def title(self): + """Gets the title of this ProblemDetails. # noqa: E501 + + A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization. If type is given and other than \"about:blank\", this attribute shall also be provided. A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4). # noqa: E501 + + :return: The title of this ProblemDetails. # noqa: E501 + :rtype: str + """ + return self._title + + @title.setter + def title(self, title): + """Sets the title of this ProblemDetails. + + A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization. If type is given and other than \"about:blank\", this attribute shall also be provided. A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4). # noqa: E501 + + :param title: The title of this ProblemDetails. # noqa: E501 + :type: str + """ + + self._title = title + + @property + def status(self): + """Gets the status of this ProblemDetails. # noqa: E501 + + The HTTP status code for this occurrence of the problem. The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. # noqa: E501 + + :return: The status of this ProblemDetails. # noqa: E501 + :rtype: int + """ + return self._status + + @status.setter + def status(self, status): + """Sets the status of this ProblemDetails. + + The HTTP status code for this occurrence of the problem. The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. # noqa: E501 + + :param status: The status of this ProblemDetails. # noqa: E501 + :type: int + """ + if status is None: + raise ValueError("Invalid value for `status`, must not be `None`") # noqa: E501 + + self._status = status + + @property + def detail(self): + """Gets the detail of this ProblemDetails. # noqa: E501 + + A human-readable explanation specific to this occurrence of the problem. # noqa: E501 + + :return: The detail of this ProblemDetails. # noqa: E501 + :rtype: str + """ + return self._detail + + @detail.setter + def detail(self, detail): + """Sets the detail of this ProblemDetails. + + A human-readable explanation specific to this occurrence of the problem. # noqa: E501 + + :param detail: The detail of this ProblemDetails. # noqa: E501 + :type: str + """ + if detail is None: + raise ValueError("Invalid value for `detail`, must not be `None`") # noqa: E501 + + self._detail = detail + + @property + def instance(self): + """Gets the instance of this ProblemDetails. # noqa: E501 + + A URI reference that identifies the specific occurrence of the problem. It may yield further information if dereferenced. # noqa: E501 + + :return: The instance of this ProblemDetails. # noqa: E501 + :rtype: str + """ + return self._instance + + @instance.setter + def instance(self, instance): + """Sets the instance of this ProblemDetails. + + A URI reference that identifies the specific occurrence of the problem. It may yield further information if dereferenced. # noqa: E501 + + :param instance: The instance of this ProblemDetails. # noqa: E501 + :type: str + """ + + self._instance = instance + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ProblemDetails, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ProblemDetails): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/process.py b/examples/demo9/python/mecapp/swagger_client/models/process.py new file mode 100644 index 000000000..1015cd633 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/process.py @@ -0,0 +1,778 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Process(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'name': 'str', + 'type': 'str', + 'is_external': 'bool', + 'image': 'str', + 'environment': 'str', + 'command_arguments': 'str', + 'command_exe': 'str', + 'service_config': 'ServiceConfig', + 'gpu_config': 'GpuConfig', + 'memory_config': 'MemoryConfig', + 'cpu_config': 'CpuConfig', + 'external_config': 'ExternalConfig', + 'status': 'str', + 'user_chart_location': 'str', + 'user_chart_alternate_values': 'str', + 'user_chart_group': 'str', + 'meta': 'dict(str, str)', + 'user_meta': 'dict(str, str)', + 'net_char': 'NetworkCharacteristics', + 'app_latency': 'int', + 'app_latency_variation': 'int', + 'app_throughput': 'int', + 'app_packet_loss': 'float', + 'placement_id': 'str' + } + + attribute_map = { + 'id': 'id', + 'name': 'name', + 'type': 'type', + 'is_external': 'isExternal', + 'image': 'image', + 'environment': 'environment', + 'command_arguments': 'commandArguments', + 'command_exe': 'commandExe', + 'service_config': 'serviceConfig', + 'gpu_config': 'gpuConfig', + 'memory_config': 'memoryConfig', + 'cpu_config': 'cpuConfig', + 'external_config': 'externalConfig', + 'status': 'status', + 'user_chart_location': 'userChartLocation', + 'user_chart_alternate_values': 'userChartAlternateValues', + 'user_chart_group': 'userChartGroup', + 'meta': 'meta', + 'user_meta': 'userMeta', + 'net_char': 'netChar', + 'app_latency': 'appLatency', + 'app_latency_variation': 'appLatencyVariation', + 'app_throughput': 'appThroughput', + 'app_packet_loss': 'appPacketLoss', + 'placement_id': 'placementId' + } + + def __init__(self, id=None, name=None, type=None, is_external=None, image=None, environment=None, command_arguments=None, command_exe=None, service_config=None, gpu_config=None, memory_config=None, cpu_config=None, external_config=None, status=None, user_chart_location=None, user_chart_alternate_values=None, user_chart_group=None, meta=None, user_meta=None, net_char=None, app_latency=None, app_latency_variation=None, app_throughput=None, app_packet_loss=None, placement_id=None): # noqa: E501 + """Process - a model defined in Swagger""" # noqa: E501 + self._id = None + self._name = None + self._type = None + self._is_external = None + self._image = None + self._environment = None + self._command_arguments = None + self._command_exe = None + self._service_config = None + self._gpu_config = None + self._memory_config = None + self._cpu_config = None + self._external_config = None + self._status = None + self._user_chart_location = None + self._user_chart_alternate_values = None + self._user_chart_group = None + self._meta = None + self._user_meta = None + self._net_char = None + self._app_latency = None + self._app_latency_variation = None + self._app_throughput = None + self._app_packet_loss = None + self._placement_id = None + self.discriminator = None + if id is not None: + self.id = id + if name is not None: + self.name = name + if type is not None: + self.type = type + if is_external is not None: + self.is_external = is_external + if image is not None: + self.image = image + if environment is not None: + self.environment = environment + if command_arguments is not None: + self.command_arguments = command_arguments + if command_exe is not None: + self.command_exe = command_exe + if service_config is not None: + self.service_config = service_config + if gpu_config is not None: + self.gpu_config = gpu_config + if memory_config is not None: + self.memory_config = memory_config + if cpu_config is not None: + self.cpu_config = cpu_config + if external_config is not None: + self.external_config = external_config + if status is not None: + self.status = status + if user_chart_location is not None: + self.user_chart_location = user_chart_location + if user_chart_alternate_values is not None: + self.user_chart_alternate_values = user_chart_alternate_values + if user_chart_group is not None: + self.user_chart_group = user_chart_group + if meta is not None: + self.meta = meta + if user_meta is not None: + self.user_meta = user_meta + if net_char is not None: + self.net_char = net_char + if app_latency is not None: + self.app_latency = app_latency + if app_latency_variation is not None: + self.app_latency_variation = app_latency_variation + if app_throughput is not None: + self.app_throughput = app_throughput + if app_packet_loss is not None: + self.app_packet_loss = app_packet_loss + if placement_id is not None: + self.placement_id = placement_id + + @property + def id(self): + """Gets the id of this Process. # noqa: E501 + + Unique process ID # noqa: E501 + + :return: The id of this Process. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this Process. + + Unique process ID # noqa: E501 + + :param id: The id of this Process. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this Process. # noqa: E501 + + Process name # noqa: E501 + + :return: The name of this Process. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this Process. + + Process name # noqa: E501 + + :param name: The name of this Process. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def type(self): + """Gets the type of this Process. # noqa: E501 + + Process type # noqa: E501 + + :return: The type of this Process. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this Process. + + Process type # noqa: E501 + + :param type: The type of this Process. # noqa: E501 + :type: str + """ + allowed_values = ["UE-APP", "EDGE-APP", "MEC-SVC", "CLOUD-APP"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def is_external(self): + """Gets the is_external of this Process. # noqa: E501 + + true: process is external to MEEP false: process is internal to MEEP # noqa: E501 + + :return: The is_external of this Process. # noqa: E501 + :rtype: bool + """ + return self._is_external + + @is_external.setter + def is_external(self, is_external): + """Sets the is_external of this Process. + + true: process is external to MEEP false: process is internal to MEEP # noqa: E501 + + :param is_external: The is_external of this Process. # noqa: E501 + :type: bool + """ + + self._is_external = is_external + + @property + def image(self): + """Gets the image of this Process. # noqa: E501 + + Docker image to deploy inside MEEP # noqa: E501 + + :return: The image of this Process. # noqa: E501 + :rtype: str + """ + return self._image + + @image.setter + def image(self, image): + """Sets the image of this Process. + + Docker image to deploy inside MEEP # noqa: E501 + + :param image: The image of this Process. # noqa: E501 + :type: str + """ + + self._image = image + + @property + def environment(self): + """Gets the environment of this Process. # noqa: E501 + + Environment variables using the format NAME=\"value\",NAME=\"value\",NAME=\"value\" # noqa: E501 + + :return: The environment of this Process. # noqa: E501 + :rtype: str + """ + return self._environment + + @environment.setter + def environment(self, environment): + """Sets the environment of this Process. + + Environment variables using the format NAME=\"value\",NAME=\"value\",NAME=\"value\" # noqa: E501 + + :param environment: The environment of this Process. # noqa: E501 + :type: str + """ + + self._environment = environment + + @property + def command_arguments(self): + """Gets the command_arguments of this Process. # noqa: E501 + + Arguments to command executable # noqa: E501 + + :return: The command_arguments of this Process. # noqa: E501 + :rtype: str + """ + return self._command_arguments + + @command_arguments.setter + def command_arguments(self, command_arguments): + """Sets the command_arguments of this Process. + + Arguments to command executable # noqa: E501 + + :param command_arguments: The command_arguments of this Process. # noqa: E501 + :type: str + """ + + self._command_arguments = command_arguments + + @property + def command_exe(self): + """Gets the command_exe of this Process. # noqa: E501 + + Executable to invoke at container start up # noqa: E501 + + :return: The command_exe of this Process. # noqa: E501 + :rtype: str + """ + return self._command_exe + + @command_exe.setter + def command_exe(self, command_exe): + """Sets the command_exe of this Process. + + Executable to invoke at container start up # noqa: E501 + + :param command_exe: The command_exe of this Process. # noqa: E501 + :type: str + """ + + self._command_exe = command_exe + + @property + def service_config(self): + """Gets the service_config of this Process. # noqa: E501 + + + :return: The service_config of this Process. # noqa: E501 + :rtype: ServiceConfig + """ + return self._service_config + + @service_config.setter + def service_config(self, service_config): + """Sets the service_config of this Process. + + + :param service_config: The service_config of this Process. # noqa: E501 + :type: ServiceConfig + """ + + self._service_config = service_config + + @property + def gpu_config(self): + """Gets the gpu_config of this Process. # noqa: E501 + + + :return: The gpu_config of this Process. # noqa: E501 + :rtype: GpuConfig + """ + return self._gpu_config + + @gpu_config.setter + def gpu_config(self, gpu_config): + """Sets the gpu_config of this Process. + + + :param gpu_config: The gpu_config of this Process. # noqa: E501 + :type: GpuConfig + """ + + self._gpu_config = gpu_config + + @property + def memory_config(self): + """Gets the memory_config of this Process. # noqa: E501 + + + :return: The memory_config of this Process. # noqa: E501 + :rtype: MemoryConfig + """ + return self._memory_config + + @memory_config.setter + def memory_config(self, memory_config): + """Sets the memory_config of this Process. + + + :param memory_config: The memory_config of this Process. # noqa: E501 + :type: MemoryConfig + """ + + self._memory_config = memory_config + + @property + def cpu_config(self): + """Gets the cpu_config of this Process. # noqa: E501 + + + :return: The cpu_config of this Process. # noqa: E501 + :rtype: CpuConfig + """ + return self._cpu_config + + @cpu_config.setter + def cpu_config(self, cpu_config): + """Sets the cpu_config of this Process. + + + :param cpu_config: The cpu_config of this Process. # noqa: E501 + :type: CpuConfig + """ + + self._cpu_config = cpu_config + + @property + def external_config(self): + """Gets the external_config of this Process. # noqa: E501 + + + :return: The external_config of this Process. # noqa: E501 + :rtype: ExternalConfig + """ + return self._external_config + + @external_config.setter + def external_config(self, external_config): + """Sets the external_config of this Process. + + + :param external_config: The external_config of this Process. # noqa: E501 + :type: ExternalConfig + """ + + self._external_config = external_config + + @property + def status(self): + """Gets the status of this Process. # noqa: E501 + + Process status # noqa: E501 + + :return: The status of this Process. # noqa: E501 + :rtype: str + """ + return self._status + + @status.setter + def status(self, status): + """Sets the status of this Process. + + Process status # noqa: E501 + + :param status: The status of this Process. # noqa: E501 + :type: str + """ + + self._status = status + + @property + def user_chart_location(self): + """Gets the user_chart_location of this Process. # noqa: E501 + + Chart location for the deployment of the chart provided by the user # noqa: E501 + + :return: The user_chart_location of this Process. # noqa: E501 + :rtype: str + """ + return self._user_chart_location + + @user_chart_location.setter + def user_chart_location(self, user_chart_location): + """Sets the user_chart_location of this Process. + + Chart location for the deployment of the chart provided by the user # noqa: E501 + + :param user_chart_location: The user_chart_location of this Process. # noqa: E501 + :type: str + """ + + self._user_chart_location = user_chart_location + + @property + def user_chart_alternate_values(self): + """Gets the user_chart_alternate_values of this Process. # noqa: E501 + + Chart values.yaml file location for the deployment of the chart provided by the user # noqa: E501 + + :return: The user_chart_alternate_values of this Process. # noqa: E501 + :rtype: str + """ + return self._user_chart_alternate_values + + @user_chart_alternate_values.setter + def user_chart_alternate_values(self, user_chart_alternate_values): + """Sets the user_chart_alternate_values of this Process. + + Chart values.yaml file location for the deployment of the chart provided by the user # noqa: E501 + + :param user_chart_alternate_values: The user_chart_alternate_values of this Process. # noqa: E501 + :type: str + """ + + self._user_chart_alternate_values = user_chart_alternate_values + + @property + def user_chart_group(self): + """Gets the user_chart_group of this Process. # noqa: E501 + + Chart supplemental information related to the group (service) # noqa: E501 + + :return: The user_chart_group of this Process. # noqa: E501 + :rtype: str + """ + return self._user_chart_group + + @user_chart_group.setter + def user_chart_group(self, user_chart_group): + """Sets the user_chart_group of this Process. + + Chart supplemental information related to the group (service) # noqa: E501 + + :param user_chart_group: The user_chart_group of this Process. # noqa: E501 + :type: str + """ + + self._user_chart_group = user_chart_group + + @property + def meta(self): + """Gets the meta of this Process. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The meta of this Process. # noqa: E501 + :rtype: dict(str, str) + """ + return self._meta + + @meta.setter + def meta(self, meta): + """Sets the meta of this Process. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param meta: The meta of this Process. # noqa: E501 + :type: dict(str, str) + """ + + self._meta = meta + + @property + def user_meta(self): + """Gets the user_meta of this Process. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The user_meta of this Process. # noqa: E501 + :rtype: dict(str, str) + """ + return self._user_meta + + @user_meta.setter + def user_meta(self, user_meta): + """Sets the user_meta of this Process. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param user_meta: The user_meta of this Process. # noqa: E501 + :type: dict(str, str) + """ + + self._user_meta = user_meta + + @property + def net_char(self): + """Gets the net_char of this Process. # noqa: E501 + + + :return: The net_char of this Process. # noqa: E501 + :rtype: NetworkCharacteristics + """ + return self._net_char + + @net_char.setter + def net_char(self, net_char): + """Sets the net_char of this Process. + + + :param net_char: The net_char of this Process. # noqa: E501 + :type: NetworkCharacteristics + """ + + self._net_char = net_char + + @property + def app_latency(self): + """Gets the app_latency of this Process. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :return: The app_latency of this Process. # noqa: E501 + :rtype: int + """ + return self._app_latency + + @app_latency.setter + def app_latency(self, app_latency): + """Sets the app_latency of this Process. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latency # noqa: E501 + + :param app_latency: The app_latency of this Process. # noqa: E501 + :type: int + """ + + self._app_latency = app_latency + + @property + def app_latency_variation(self): + """Gets the app_latency_variation of this Process. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :return: The app_latency_variation of this Process. # noqa: E501 + :rtype: int + """ + return self._app_latency_variation + + @app_latency_variation.setter + def app_latency_variation(self, app_latency_variation): + """Sets the app_latency_variation of this Process. + + **DEPRECATED** As of release 1.5.0, replaced by netChar latencyVariation # noqa: E501 + + :param app_latency_variation: The app_latency_variation of this Process. # noqa: E501 + :type: int + """ + + self._app_latency_variation = app_latency_variation + + @property + def app_throughput(self): + """Gets the app_throughput of this Process. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :return: The app_throughput of this Process. # noqa: E501 + :rtype: int + """ + return self._app_throughput + + @app_throughput.setter + def app_throughput(self, app_throughput): + """Sets the app_throughput of this Process. + + **DEPRECATED** As of release 1.5.0, replaced by netChar throughputUl and throughputDl # noqa: E501 + + :param app_throughput: The app_throughput of this Process. # noqa: E501 + :type: int + """ + + self._app_throughput = app_throughput + + @property + def app_packet_loss(self): + """Gets the app_packet_loss of this Process. # noqa: E501 + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :return: The app_packet_loss of this Process. # noqa: E501 + :rtype: float + """ + return self._app_packet_loss + + @app_packet_loss.setter + def app_packet_loss(self, app_packet_loss): + """Sets the app_packet_loss of this Process. + + **DEPRECATED** As of release 1.5.0, replaced by netChar packetLoss # noqa: E501 + + :param app_packet_loss: The app_packet_loss of this Process. # noqa: E501 + :type: float + """ + + self._app_packet_loss = app_packet_loss + + @property + def placement_id(self): + """Gets the placement_id of this Process. # noqa: E501 + + Identifier used for process placement in AdvantEDGE cluster # noqa: E501 + + :return: The placement_id of this Process. # noqa: E501 + :rtype: str + """ + return self._placement_id + + @placement_id.setter + def placement_id(self, placement_id): + """Sets the placement_id of this Process. + + Identifier used for process placement in AdvantEDGE cluster # noqa: E501 + + :param placement_id: The placement_id of this Process. # noqa: E501 + :type: str + """ + + self._placement_id = placement_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Process, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Process): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/sandbox.py b/examples/demo9/python/mecapp/swagger_client/models/sandbox.py new file mode 100644 index 000000000..3630ba159 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/sandbox.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Sandbox(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'name': 'str' + } + + attribute_map = { + 'name': 'name' + } + + def __init__(self, name=None): # noqa: E501 + """Sandbox - a model defined in Swagger""" # noqa: E501 + self._name = None + self.discriminator = None + if name is not None: + self.name = name + + @property + def name(self): + """Gets the name of this Sandbox. # noqa: E501 + + Sandbox name # noqa: E501 + + :return: The name of this Sandbox. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this Sandbox. + + Sandbox name # noqa: E501 + + :param name: The name of this Sandbox. # noqa: E501 + :type: str + """ + + self._name = name + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Sandbox, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Sandbox): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/sandbox_app_instances.py b/examples/demo9/python/mecapp/swagger_client/models/sandbox_app_instances.py new file mode 100644 index 000000000..c71fc6fe2 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/sandbox_app_instances.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class SandboxAppInstances(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str' + } + + attribute_map = { + 'id': 'id' + } + + def __init__(self, id=None): # noqa: E501 + """SandboxAppInstances - a model defined in Swagger""" # noqa: E501 + self._id = None + self.discriminator = None + self.id = id + + @property + def id(self): + """Gets the id of this SandboxAppInstances. # noqa: E501 + + The application instance identifier. # noqa: E501 + + :return: The id of this SandboxAppInstances. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this SandboxAppInstances. + + The application instance identifier. # noqa: E501 + + :param id: The id of this SandboxAppInstances. # noqa: E501 + :type: str + """ + if id is None: + raise ValueError("Invalid value for `id`, must not be `None`") # noqa: E501 + + self._id = id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(SandboxAppInstances, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, SandboxAppInstances): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/sandbox_logs_subscriptions.py b/examples/demo9/python/mecapp/swagger_client/models/sandbox_logs_subscriptions.py new file mode 100644 index 000000000..66b8cfde8 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/sandbox_logs_subscriptions.py @@ -0,0 +1,141 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class SandboxLogsSubscriptions(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'callback_reference': 'str', + 'subscription_reference': 'str' + } + + attribute_map = { + 'callback_reference': 'callbackReference', + 'subscription_reference': 'subscriptionReference' + } + + def __init__(self, callback_reference=None, subscription_reference=None): # noqa: E501 + """SandboxLogsSubscriptions - a model defined in Swagger""" # noqa: E501 + self._callback_reference = None + self._subscription_reference = None + self.discriminator = None + self.callback_reference = callback_reference + if subscription_reference is not None: + self.subscription_reference = subscription_reference + + @property + def callback_reference(self): + """Gets the callback_reference of this SandboxLogsSubscriptions. # noqa: E501 + + The callback to notify log messages. # noqa: E501 + + :return: The callback_reference of this SandboxLogsSubscriptions. # noqa: E501 + :rtype: str + """ + return self._callback_reference + + @callback_reference.setter + def callback_reference(self, callback_reference): + """Sets the callback_reference of this SandboxLogsSubscriptions. + + The callback to notify log messages. # noqa: E501 + + :param callback_reference: The callback_reference of this SandboxLogsSubscriptions. # noqa: E501 + :type: str + """ + if callback_reference is None: + raise ValueError("Invalid value for `callback_reference`, must not be `None`") # noqa: E501 + + self._callback_reference = callback_reference + + @property + def subscription_reference(self): + """Gets the subscription_reference of this SandboxLogsSubscriptions. # noqa: E501 + + The reference of the subscription. # noqa: E501 + + :return: The subscription_reference of this SandboxLogsSubscriptions. # noqa: E501 + :rtype: str + """ + return self._subscription_reference + + @subscription_reference.setter + def subscription_reference(self, subscription_reference): + """Sets the subscription_reference of this SandboxLogsSubscriptions. + + The reference of the subscription. # noqa: E501 + + :param subscription_reference: The subscription_reference of this SandboxLogsSubscriptions. # noqa: E501 + :type: str + """ + + self._subscription_reference = subscription_reference + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(SandboxLogsSubscriptions, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, SandboxLogsSubscriptions): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/sandbox_mec_services.py b/examples/demo9/python/mecapp/swagger_client/models/sandbox_mec_services.py new file mode 100644 index 000000000..042140130 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/sandbox_mec_services.py @@ -0,0 +1,141 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class SandboxMecServices(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'service_id': 'str' + } + + attribute_map = { + 'id': 'id', + 'service_id': 'service_id' + } + + def __init__(self, id=None, service_id=None): # noqa: E501 + """SandboxMecServices - a model defined in Swagger""" # noqa: E501 + self._id = None + self._service_id = None + self.discriminator = None + self.id = id + if service_id is not None: + self.service_id = service_id + + @property + def id(self): + """Gets the id of this SandboxMecServices. # noqa: E501 + + The MEC service name. # noqa: E501 + + :return: The id of this SandboxMecServices. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this SandboxMecServices. + + The MEC service name. # noqa: E501 + + :param id: The id of this SandboxMecServices. # noqa: E501 + :type: str + """ + if id is None: + raise ValueError("Invalid value for `id`, must not be `None`") # noqa: E501 + + self._id = id + + @property + def service_id(self): + """Gets the service_id of this SandboxMecServices. # noqa: E501 + + When a MEC service is selected, this field contains a token which shall be used in MEC service API URI. # noqa: E501 + + :return: The service_id of this SandboxMecServices. # noqa: E501 + :rtype: str + """ + return self._service_id + + @service_id.setter + def service_id(self, service_id): + """Sets the service_id of this SandboxMecServices. + + When a MEC service is selected, this field contains a token which shall be used in MEC service API URI. # noqa: E501 + + :param service_id: The service_id of this SandboxMecServices. # noqa: E501 + :type: str + """ + + self._service_id = service_id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(SandboxMecServices, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, SandboxMecServices): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/sandbox_network_scenario.py b/examples/demo9/python/mecapp/swagger_client/models/sandbox_network_scenario.py new file mode 100644 index 000000000..333eb735d --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/sandbox_network_scenario.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class SandboxNetworkScenario(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str' + } + + attribute_map = { + 'id': 'id' + } + + def __init__(self, id=None): # noqa: E501 + """SandboxNetworkScenario - a model defined in Swagger""" # noqa: E501 + self._id = None + self.discriminator = None + self.id = id + + @property + def id(self): + """Gets the id of this SandboxNetworkScenario. # noqa: E501 + + The network scenario name. # noqa: E501 + + :return: The id of this SandboxNetworkScenario. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this SandboxNetworkScenario. + + The network scenario name. # noqa: E501 + + :param id: The id of this SandboxNetworkScenario. # noqa: E501 + :type: str + """ + if id is None: + raise ValueError("Invalid value for `id`, must not be `None`") # noqa: E501 + + self._id = id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(SandboxNetworkScenario, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, SandboxNetworkScenario): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/scenario.py b/examples/demo9/python/mecapp/swagger_client/models/scenario.py new file mode 100644 index 000000000..c4a9dcc2d --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/scenario.py @@ -0,0 +1,248 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Scenario(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'version': 'str', + 'id': 'str', + 'name': 'str', + 'description': 'str', + 'config': 'ScenarioConfig', + 'deployment': 'Deployment' + } + + attribute_map = { + 'version': 'version', + 'id': 'id', + 'name': 'name', + 'description': 'description', + 'config': 'config', + 'deployment': 'deployment' + } + + def __init__(self, version=None, id=None, name=None, description=None, config=None, deployment=None): # noqa: E501 + """Scenario - a model defined in Swagger""" # noqa: E501 + self._version = None + self._id = None + self._name = None + self._description = None + self._config = None + self._deployment = None + self.discriminator = None + if version is not None: + self.version = version + if id is not None: + self.id = id + if name is not None: + self.name = name + if description is not None: + self.description = description + if config is not None: + self.config = config + if deployment is not None: + self.deployment = deployment + + @property + def version(self): + """Gets the version of this Scenario. # noqa: E501 + + Scenario version # noqa: E501 + + :return: The version of this Scenario. # noqa: E501 + :rtype: str + """ + return self._version + + @version.setter + def version(self, version): + """Sets the version of this Scenario. + + Scenario version # noqa: E501 + + :param version: The version of this Scenario. # noqa: E501 + :type: str + """ + + self._version = version + + @property + def id(self): + """Gets the id of this Scenario. # noqa: E501 + + Unique scenario ID # noqa: E501 + + :return: The id of this Scenario. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this Scenario. + + Unique scenario ID # noqa: E501 + + :param id: The id of this Scenario. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this Scenario. # noqa: E501 + + Unique scenario name # noqa: E501 + + :return: The name of this Scenario. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this Scenario. + + Unique scenario name # noqa: E501 + + :param name: The name of this Scenario. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def description(self): + """Gets the description of this Scenario. # noqa: E501 + + User description of the scenario. # noqa: E501 + + :return: The description of this Scenario. # noqa: E501 + :rtype: str + """ + return self._description + + @description.setter + def description(self, description): + """Sets the description of this Scenario. + + User description of the scenario. # noqa: E501 + + :param description: The description of this Scenario. # noqa: E501 + :type: str + """ + + self._description = description + + @property + def config(self): + """Gets the config of this Scenario. # noqa: E501 + + + :return: The config of this Scenario. # noqa: E501 + :rtype: ScenarioConfig + """ + return self._config + + @config.setter + def config(self, config): + """Sets the config of this Scenario. + + + :param config: The config of this Scenario. # noqa: E501 + :type: ScenarioConfig + """ + + self._config = config + + @property + def deployment(self): + """Gets the deployment of this Scenario. # noqa: E501 + + + :return: The deployment of this Scenario. # noqa: E501 + :rtype: Deployment + """ + return self._deployment + + @deployment.setter + def deployment(self, deployment): + """Sets the deployment of this Scenario. + + + :param deployment: The deployment of this Scenario. # noqa: E501 + :type: Deployment + """ + + self._deployment = deployment + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Scenario, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Scenario): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/scenario_config.py b/examples/demo9/python/mecapp/swagger_client/models/scenario_config.py new file mode 100644 index 000000000..126dad37e --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/scenario_config.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ScenarioConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'visualization': 'str', + 'other': 'str' + } + + attribute_map = { + 'visualization': 'visualization', + 'other': 'other' + } + + def __init__(self, visualization=None, other=None): # noqa: E501 + """ScenarioConfig - a model defined in Swagger""" # noqa: E501 + self._visualization = None + self._other = None + self.discriminator = None + if visualization is not None: + self.visualization = visualization + if other is not None: + self.other = other + + @property + def visualization(self): + """Gets the visualization of this ScenarioConfig. # noqa: E501 + + Visualization configuration # noqa: E501 + + :return: The visualization of this ScenarioConfig. # noqa: E501 + :rtype: str + """ + return self._visualization + + @visualization.setter + def visualization(self, visualization): + """Sets the visualization of this ScenarioConfig. + + Visualization configuration # noqa: E501 + + :param visualization: The visualization of this ScenarioConfig. # noqa: E501 + :type: str + """ + + self._visualization = visualization + + @property + def other(self): + """Gets the other of this ScenarioConfig. # noqa: E501 + + Other scenario configuration # noqa: E501 + + :return: The other of this ScenarioConfig. # noqa: E501 + :rtype: str + """ + return self._other + + @other.setter + def other(self, other): + """Sets the other of this ScenarioConfig. + + Other scenario configuration # noqa: E501 + + :param other: The other of this ScenarioConfig. # noqa: E501 + :type: str + """ + + self._other = other + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ScenarioConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ScenarioConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/service_config.py b/examples/demo9/python/mecapp/swagger_client/models/service_config.py new file mode 100644 index 000000000..65b7a3697 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/service_config.py @@ -0,0 +1,166 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ServiceConfig(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'name': 'str', + 'me_svc_name': 'str', + 'ports': 'list[ServicePort]' + } + + attribute_map = { + 'name': 'name', + 'me_svc_name': 'meSvcName', + 'ports': 'ports' + } + + def __init__(self, name=None, me_svc_name=None, ports=None): # noqa: E501 + """ServiceConfig - a model defined in Swagger""" # noqa: E501 + self._name = None + self._me_svc_name = None + self._ports = None + self.discriminator = None + if name is not None: + self.name = name + if me_svc_name is not None: + self.me_svc_name = me_svc_name + if ports is not None: + self.ports = ports + + @property + def name(self): + """Gets the name of this ServiceConfig. # noqa: E501 + + Unique service name # noqa: E501 + + :return: The name of this ServiceConfig. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this ServiceConfig. + + Unique service name # noqa: E501 + + :param name: The name of this ServiceConfig. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def me_svc_name(self): + """Gets the me_svc_name of this ServiceConfig. # noqa: E501 + + Multi-Edge service name, if any # noqa: E501 + + :return: The me_svc_name of this ServiceConfig. # noqa: E501 + :rtype: str + """ + return self._me_svc_name + + @me_svc_name.setter + def me_svc_name(self, me_svc_name): + """Sets the me_svc_name of this ServiceConfig. + + Multi-Edge service name, if any # noqa: E501 + + :param me_svc_name: The me_svc_name of this ServiceConfig. # noqa: E501 + :type: str + """ + + self._me_svc_name = me_svc_name + + @property + def ports(self): + """Gets the ports of this ServiceConfig. # noqa: E501 + + + :return: The ports of this ServiceConfig. # noqa: E501 + :rtype: list[ServicePort] + """ + return self._ports + + @ports.setter + def ports(self, ports): + """Sets the ports of this ServiceConfig. + + + :param ports: The ports of this ServiceConfig. # noqa: E501 + :type: list[ServicePort] + """ + + self._ports = ports + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ServiceConfig, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ServiceConfig): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/service_port.py b/examples/demo9/python/mecapp/swagger_client/models/service_port.py new file mode 100644 index 000000000..6b7d34e70 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/service_port.py @@ -0,0 +1,168 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class ServicePort(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'protocol': 'str', + 'port': 'int', + 'external_port': 'int' + } + + attribute_map = { + 'protocol': 'protocol', + 'port': 'port', + 'external_port': 'externalPort' + } + + def __init__(self, protocol=None, port=None, external_port=None): # noqa: E501 + """ServicePort - a model defined in Swagger""" # noqa: E501 + self._protocol = None + self._port = None + self._external_port = None + self.discriminator = None + if protocol is not None: + self.protocol = protocol + if port is not None: + self.port = port + if external_port is not None: + self.external_port = external_port + + @property + def protocol(self): + """Gets the protocol of this ServicePort. # noqa: E501 + + Protocol that the application is using (TCP or UDP) # noqa: E501 + + :return: The protocol of this ServicePort. # noqa: E501 + :rtype: str + """ + return self._protocol + + @protocol.setter + def protocol(self, protocol): + """Sets the protocol of this ServicePort. + + Protocol that the application is using (TCP or UDP) # noqa: E501 + + :param protocol: The protocol of this ServicePort. # noqa: E501 + :type: str + """ + + self._protocol = protocol + + @property + def port(self): + """Gets the port of this ServicePort. # noqa: E501 + + Port number that the service is listening on # noqa: E501 + + :return: The port of this ServicePort. # noqa: E501 + :rtype: int + """ + return self._port + + @port.setter + def port(self, port): + """Sets the port of this ServicePort. + + Port number that the service is listening on # noqa: E501 + + :param port: The port of this ServicePort. # noqa: E501 + :type: int + """ + + self._port = port + + @property + def external_port(self): + """Gets the external_port of this ServicePort. # noqa: E501 + + External port number on which to expose the application (30000 - 32767)
  • Only one application allowed per external port
  • Scenario builder must configure to prevent conflicts # noqa: E501 + + :return: The external_port of this ServicePort. # noqa: E501 + :rtype: int + """ + return self._external_port + + @external_port.setter + def external_port(self, external_port): + """Sets the external_port of this ServicePort. + + External port number on which to expose the application (30000 - 32767)
  • Only one application allowed per external port
  • Scenario builder must configure to prevent conflicts # noqa: E501 + + :param external_port: The external_port of this ServicePort. # noqa: E501 + :type: int + """ + + self._external_port = external_port + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(ServicePort, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ServicePort): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/ue.py b/examples/demo9/python/mecapp/swagger_client/models/ue.py new file mode 100644 index 000000000..d27f1f3e6 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/ue.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class UE(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str' + } + + attribute_map = { + 'id': 'id' + } + + def __init__(self, id=None): # noqa: E501 + """UE - a model defined in Swagger""" # noqa: E501 + self._id = None + self.discriminator = None + self.id = id + + @property + def id(self): + """Gets the id of this UE. # noqa: E501 + + The UE name. # noqa: E501 + + :return: The id of this UE. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this UE. + + The UE name. # noqa: E501 + + :param id: The id of this UE. # noqa: E501 + :type: str + """ + if id is None: + raise ValueError("Invalid value for `id`, must not be `None`") # noqa: E501 + + self._id = id + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(UE, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, UE): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/models/zone.py b/examples/demo9/python/mecapp/swagger_client/models/zone.py new file mode 100644 index 000000000..c7b2dd02d --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/models/zone.py @@ -0,0 +1,618 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +import pprint +import re # noqa: F401 + +import six + +class Zone(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { + 'id': 'str', + 'name': 'str', + 'type': 'str', + 'net_char': 'NetworkCharacteristics', + 'inter_fog_latency': 'int', + 'inter_fog_latency_variation': 'int', + 'inter_fog_throughput': 'int', + 'inter_fog_packet_loss': 'float', + 'inter_edge_latency': 'int', + 'inter_edge_latency_variation': 'int', + 'inter_edge_throughput': 'int', + 'inter_edge_packet_loss': 'float', + 'edge_fog_latency': 'int', + 'edge_fog_latency_variation': 'int', + 'edge_fog_throughput': 'int', + 'edge_fog_packet_loss': 'float', + 'meta': 'dict(str, str)', + 'user_meta': 'dict(str, str)', + 'network_locations': 'list[NetworkLocation]' + } + + attribute_map = { + 'id': 'id', + 'name': 'name', + 'type': 'type', + 'net_char': 'netChar', + 'inter_fog_latency': 'interFogLatency', + 'inter_fog_latency_variation': 'interFogLatencyVariation', + 'inter_fog_throughput': 'interFogThroughput', + 'inter_fog_packet_loss': 'interFogPacketLoss', + 'inter_edge_latency': 'interEdgeLatency', + 'inter_edge_latency_variation': 'interEdgeLatencyVariation', + 'inter_edge_throughput': 'interEdgeThroughput', + 'inter_edge_packet_loss': 'interEdgePacketLoss', + 'edge_fog_latency': 'edgeFogLatency', + 'edge_fog_latency_variation': 'edgeFogLatencyVariation', + 'edge_fog_throughput': 'edgeFogThroughput', + 'edge_fog_packet_loss': 'edgeFogPacketLoss', + 'meta': 'meta', + 'user_meta': 'userMeta', + 'network_locations': 'networkLocations' + } + + def __init__(self, id=None, name=None, type=None, net_char=None, inter_fog_latency=None, inter_fog_latency_variation=None, inter_fog_throughput=None, inter_fog_packet_loss=None, inter_edge_latency=None, inter_edge_latency_variation=None, inter_edge_throughput=None, inter_edge_packet_loss=None, edge_fog_latency=None, edge_fog_latency_variation=None, edge_fog_throughput=None, edge_fog_packet_loss=None, meta=None, user_meta=None, network_locations=None): # noqa: E501 + """Zone - a model defined in Swagger""" # noqa: E501 + self._id = None + self._name = None + self._type = None + self._net_char = None + self._inter_fog_latency = None + self._inter_fog_latency_variation = None + self._inter_fog_throughput = None + self._inter_fog_packet_loss = None + self._inter_edge_latency = None + self._inter_edge_latency_variation = None + self._inter_edge_throughput = None + self._inter_edge_packet_loss = None + self._edge_fog_latency = None + self._edge_fog_latency_variation = None + self._edge_fog_throughput = None + self._edge_fog_packet_loss = None + self._meta = None + self._user_meta = None + self._network_locations = None + self.discriminator = None + if id is not None: + self.id = id + if name is not None: + self.name = name + if type is not None: + self.type = type + if net_char is not None: + self.net_char = net_char + if inter_fog_latency is not None: + self.inter_fog_latency = inter_fog_latency + if inter_fog_latency_variation is not None: + self.inter_fog_latency_variation = inter_fog_latency_variation + if inter_fog_throughput is not None: + self.inter_fog_throughput = inter_fog_throughput + if inter_fog_packet_loss is not None: + self.inter_fog_packet_loss = inter_fog_packet_loss + if inter_edge_latency is not None: + self.inter_edge_latency = inter_edge_latency + if inter_edge_latency_variation is not None: + self.inter_edge_latency_variation = inter_edge_latency_variation + if inter_edge_throughput is not None: + self.inter_edge_throughput = inter_edge_throughput + if inter_edge_packet_loss is not None: + self.inter_edge_packet_loss = inter_edge_packet_loss + if edge_fog_latency is not None: + self.edge_fog_latency = edge_fog_latency + if edge_fog_latency_variation is not None: + self.edge_fog_latency_variation = edge_fog_latency_variation + if edge_fog_throughput is not None: + self.edge_fog_throughput = edge_fog_throughput + if edge_fog_packet_loss is not None: + self.edge_fog_packet_loss = edge_fog_packet_loss + if meta is not None: + self.meta = meta + if user_meta is not None: + self.user_meta = user_meta + if network_locations is not None: + self.network_locations = network_locations + + @property + def id(self): + """Gets the id of this Zone. # noqa: E501 + + Unique zone ID # noqa: E501 + + :return: The id of this Zone. # noqa: E501 + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this Zone. + + Unique zone ID # noqa: E501 + + :param id: The id of this Zone. # noqa: E501 + :type: str + """ + + self._id = id + + @property + def name(self): + """Gets the name of this Zone. # noqa: E501 + + Zone name # noqa: E501 + + :return: The name of this Zone. # noqa: E501 + :rtype: str + """ + return self._name + + @name.setter + def name(self, name): + """Sets the name of this Zone. + + Zone name # noqa: E501 + + :param name: The name of this Zone. # noqa: E501 + :type: str + """ + + self._name = name + + @property + def type(self): + """Gets the type of this Zone. # noqa: E501 + + Zone type # noqa: E501 + + :return: The type of this Zone. # noqa: E501 + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this Zone. + + Zone type # noqa: E501 + + :param type: The type of this Zone. # noqa: E501 + :type: str + """ + allowed_values = ["ZONE", "COMMON"] # noqa: E501 + if type not in allowed_values: + raise ValueError( + "Invalid value for `type` ({0}), must be one of {1}" # noqa: E501 + .format(type, allowed_values) + ) + + self._type = type + + @property + def net_char(self): + """Gets the net_char of this Zone. # noqa: E501 + + + :return: The net_char of this Zone. # noqa: E501 + :rtype: NetworkCharacteristics + """ + return self._net_char + + @net_char.setter + def net_char(self, net_char): + """Sets the net_char of this Zone. + + + :param net_char: The net_char of this Zone. # noqa: E501 + :type: NetworkCharacteristics + """ + + self._net_char = net_char + + @property + def inter_fog_latency(self): + """Gets the inter_fog_latency of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_fog_latency of this Zone. # noqa: E501 + :rtype: int + """ + return self._inter_fog_latency + + @inter_fog_latency.setter + def inter_fog_latency(self, inter_fog_latency): + """Sets the inter_fog_latency of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_fog_latency: The inter_fog_latency of this Zone. # noqa: E501 + :type: int + """ + + self._inter_fog_latency = inter_fog_latency + + @property + def inter_fog_latency_variation(self): + """Gets the inter_fog_latency_variation of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_fog_latency_variation of this Zone. # noqa: E501 + :rtype: int + """ + return self._inter_fog_latency_variation + + @inter_fog_latency_variation.setter + def inter_fog_latency_variation(self, inter_fog_latency_variation): + """Sets the inter_fog_latency_variation of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_fog_latency_variation: The inter_fog_latency_variation of this Zone. # noqa: E501 + :type: int + """ + + self._inter_fog_latency_variation = inter_fog_latency_variation + + @property + def inter_fog_throughput(self): + """Gets the inter_fog_throughput of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_fog_throughput of this Zone. # noqa: E501 + :rtype: int + """ + return self._inter_fog_throughput + + @inter_fog_throughput.setter + def inter_fog_throughput(self, inter_fog_throughput): + """Sets the inter_fog_throughput of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_fog_throughput: The inter_fog_throughput of this Zone. # noqa: E501 + :type: int + """ + + self._inter_fog_throughput = inter_fog_throughput + + @property + def inter_fog_packet_loss(self): + """Gets the inter_fog_packet_loss of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_fog_packet_loss of this Zone. # noqa: E501 + :rtype: float + """ + return self._inter_fog_packet_loss + + @inter_fog_packet_loss.setter + def inter_fog_packet_loss(self, inter_fog_packet_loss): + """Sets the inter_fog_packet_loss of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_fog_packet_loss: The inter_fog_packet_loss of this Zone. # noqa: E501 + :type: float + """ + + self._inter_fog_packet_loss = inter_fog_packet_loss + + @property + def inter_edge_latency(self): + """Gets the inter_edge_latency of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_edge_latency of this Zone. # noqa: E501 + :rtype: int + """ + return self._inter_edge_latency + + @inter_edge_latency.setter + def inter_edge_latency(self, inter_edge_latency): + """Sets the inter_edge_latency of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_edge_latency: The inter_edge_latency of this Zone. # noqa: E501 + :type: int + """ + + self._inter_edge_latency = inter_edge_latency + + @property + def inter_edge_latency_variation(self): + """Gets the inter_edge_latency_variation of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_edge_latency_variation of this Zone. # noqa: E501 + :rtype: int + """ + return self._inter_edge_latency_variation + + @inter_edge_latency_variation.setter + def inter_edge_latency_variation(self, inter_edge_latency_variation): + """Sets the inter_edge_latency_variation of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_edge_latency_variation: The inter_edge_latency_variation of this Zone. # noqa: E501 + :type: int + """ + + self._inter_edge_latency_variation = inter_edge_latency_variation + + @property + def inter_edge_throughput(self): + """Gets the inter_edge_throughput of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_edge_throughput of this Zone. # noqa: E501 + :rtype: int + """ + return self._inter_edge_throughput + + @inter_edge_throughput.setter + def inter_edge_throughput(self, inter_edge_throughput): + """Sets the inter_edge_throughput of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_edge_throughput: The inter_edge_throughput of this Zone. # noqa: E501 + :type: int + """ + + self._inter_edge_throughput = inter_edge_throughput + + @property + def inter_edge_packet_loss(self): + """Gets the inter_edge_packet_loss of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :return: The inter_edge_packet_loss of this Zone. # noqa: E501 + :rtype: float + """ + return self._inter_edge_packet_loss + + @inter_edge_packet_loss.setter + def inter_edge_packet_loss(self, inter_edge_packet_loss): + """Sets the inter_edge_packet_loss of this Zone. + + **DEPRECATED** As of release 1.3.0, no longer supported # noqa: E501 + + :param inter_edge_packet_loss: The inter_edge_packet_loss of this Zone. # noqa: E501 + :type: float + """ + + self._inter_edge_packet_loss = inter_edge_packet_loss + + @property + def edge_fog_latency(self): + """Gets the edge_fog_latency of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, replaced by netChar latency # noqa: E501 + + :return: The edge_fog_latency of this Zone. # noqa: E501 + :rtype: int + """ + return self._edge_fog_latency + + @edge_fog_latency.setter + def edge_fog_latency(self, edge_fog_latency): + """Sets the edge_fog_latency of this Zone. + + **DEPRECATED** As of release 1.3.0, replaced by netChar latency # noqa: E501 + + :param edge_fog_latency: The edge_fog_latency of this Zone. # noqa: E501 + :type: int + """ + + self._edge_fog_latency = edge_fog_latency + + @property + def edge_fog_latency_variation(self): + """Gets the edge_fog_latency_variation of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, replaced by netChar latencyVariation # noqa: E501 + + :return: The edge_fog_latency_variation of this Zone. # noqa: E501 + :rtype: int + """ + return self._edge_fog_latency_variation + + @edge_fog_latency_variation.setter + def edge_fog_latency_variation(self, edge_fog_latency_variation): + """Sets the edge_fog_latency_variation of this Zone. + + **DEPRECATED** As of release 1.3.0, replaced by netChar latencyVariation # noqa: E501 + + :param edge_fog_latency_variation: The edge_fog_latency_variation of this Zone. # noqa: E501 + :type: int + """ + + self._edge_fog_latency_variation = edge_fog_latency_variation + + @property + def edge_fog_throughput(self): + """Gets the edge_fog_throughput of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, replaced by netChar throughput # noqa: E501 + + :return: The edge_fog_throughput of this Zone. # noqa: E501 + :rtype: int + """ + return self._edge_fog_throughput + + @edge_fog_throughput.setter + def edge_fog_throughput(self, edge_fog_throughput): + """Sets the edge_fog_throughput of this Zone. + + **DEPRECATED** As of release 1.3.0, replaced by netChar throughput # noqa: E501 + + :param edge_fog_throughput: The edge_fog_throughput of this Zone. # noqa: E501 + :type: int + """ + + self._edge_fog_throughput = edge_fog_throughput + + @property + def edge_fog_packet_loss(self): + """Gets the edge_fog_packet_loss of this Zone. # noqa: E501 + + **DEPRECATED** As of release 1.3.0, replaced by netChar packetLoss # noqa: E501 + + :return: The edge_fog_packet_loss of this Zone. # noqa: E501 + :rtype: float + """ + return self._edge_fog_packet_loss + + @edge_fog_packet_loss.setter + def edge_fog_packet_loss(self, edge_fog_packet_loss): + """Sets the edge_fog_packet_loss of this Zone. + + **DEPRECATED** As of release 1.3.0, replaced by netChar packetLoss # noqa: E501 + + :param edge_fog_packet_loss: The edge_fog_packet_loss of this Zone. # noqa: E501 + :type: float + """ + + self._edge_fog_packet_loss = edge_fog_packet_loss + + @property + def meta(self): + """Gets the meta of this Zone. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The meta of this Zone. # noqa: E501 + :rtype: dict(str, str) + """ + return self._meta + + @meta.setter + def meta(self, meta): + """Sets the meta of this Zone. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param meta: The meta of this Zone. # noqa: E501 + :type: dict(str, str) + """ + + self._meta = meta + + @property + def user_meta(self): + """Gets the user_meta of this Zone. # noqa: E501 + + Key/Value Pair Map (string, string) # noqa: E501 + + :return: The user_meta of this Zone. # noqa: E501 + :rtype: dict(str, str) + """ + return self._user_meta + + @user_meta.setter + def user_meta(self, user_meta): + """Sets the user_meta of this Zone. + + Key/Value Pair Map (string, string) # noqa: E501 + + :param user_meta: The user_meta of this Zone. # noqa: E501 + :type: dict(str, str) + """ + + self._user_meta = user_meta + + @property + def network_locations(self): + """Gets the network_locations of this Zone. # noqa: E501 + + + :return: The network_locations of this Zone. # noqa: E501 + :rtype: list[NetworkLocation] + """ + return self._network_locations + + @network_locations.setter + def network_locations(self, network_locations): + """Sets the network_locations of this Zone. + + + :param network_locations: The network_locations of this Zone. # noqa: E501 + :type: list[NetworkLocation] + """ + + self._network_locations = network_locations + + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + if issubclass(Zone, dict): + for key, value in self.items(): + result[key] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, Zone): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/examples/demo9/python/mecapp/swagger_client/rest.py b/examples/demo9/python/mecapp/swagger_client/rest.py new file mode 100644 index 000000000..8a076b4e7 --- /dev/null +++ b/examples/demo9/python/mecapp/swagger_client/rest.py @@ -0,0 +1,317 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.9 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import io +import json +import logging +import re +import ssl + +import certifi +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import urlencode + +try: + import urllib3 +except ImportError: + raise ImportError('Swagger python client requires urllib3.') + + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp): + self.urllib3_response = resp + self.status = resp.status + self.reason = resp.reason + self.data = resp.data + + def getheaders(self): + """Returns a dictionary of the response headers.""" + return self.urllib3_response.getheaders() + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.urllib3_response.getheader(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=None): + # urllib3.PoolManager will pass all kw parameters to connectionpool + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 + # maxsize is the number of requests to host that are allowed in parallel # noqa: E501 + # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 + + # cert_reqs + if configuration.verify_ssl: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + addition_pool_args = {} + if configuration.assert_hostname is not None: + addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 + + if maxsize is None: + if configuration.connection_pool_maxsize is not None: + maxsize = configuration.connection_pool_maxsize + else: + maxsize = 4 + + # https pool manager + if configuration.proxy: + self.pool_manager = urllib3.ProxyManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + proxy_url=configuration.proxy, + **addition_pool_args + ) + else: + self.pool_manager = urllib3.PoolManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + **addition_pool_args + ) + + def request(self, method, url, query_params=None, headers=None, + body=None, post_params=None, _preload_content=True, + _request_timeout=None): + """Perform requests. + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + + timeout = None + if _request_timeout: + if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)): # noqa: E501,F821 + timeout = urllib3.Timeout(total=_request_timeout) + elif (isinstance(_request_timeout, tuple) and + len(_request_timeout) == 2): + timeout = urllib3.Timeout( + connect=_request_timeout[0], read=_request_timeout[1]) + + if 'Content-Type' not in headers: + headers['Content-Type'] = 'application/json' + + try: + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if query_params: + url += '?' + urlencode(query_params) + if re.search('json', headers['Content-Type'], re.IGNORECASE): + request_body = '{}' + if body is not None: + request_body = json.dumps(body) + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=False, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by urllib3 will be + # overwritten. + del headers['Content-Type'] + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=True, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + # Pass a `string` parameter directly in the body to support + # other content types than Json when `body` argument is + # provided in serialized form + elif isinstance(body, str): + request_body = body + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + # For `GET`, `HEAD` + else: + r = self.pool_manager.request(method, url, + fields=query_params, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + except urllib3.exceptions.SSLError as e: + msg = "{0}\n{1}".format(type(e).__name__, str(e)) + raise ApiException(status=0, reason=msg) + + if _preload_content: + r = RESTResponse(r) + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + return r + + def GET(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def HEAD(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def OPTIONS(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + return self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def POST(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PATCH(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/examples/demo9/python/mecapp/test-requirements.txt b/examples/demo9/python/mecapp/test-requirements.txt new file mode 100644 index 000000000..2702246c0 --- /dev/null +++ b/examples/demo9/python/mecapp/test-requirements.txt @@ -0,0 +1,5 @@ +coverage>=4.0.3 +nose>=1.3.7 +pluggy>=0.3.1 +py>=1.4.31 +randomize>=0.13 diff --git a/examples/demo9/python/mecapp/test/__init__.py b/examples/demo9/python/mecapp/test/__init__.py new file mode 100644 index 000000000..576f56f87 --- /dev/null +++ b/examples/demo9/python/mecapp/test/__init__.py @@ -0,0 +1 @@ +# coding: utf-8 \ No newline at end of file diff --git a/examples/demo9/python/mecapp/test/test_application_info.py b/examples/demo9/python/mecapp/test/test_application_info.py new file mode 100644 index 000000000..e8f2df485 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_application_info.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.application_info import ApplicationInfo # noqa: E501 +from swagger_client.rest import ApiException + + +class TestApplicationInfo(unittest.TestCase): + """ApplicationInfo unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testApplicationInfo(self): + """Test ApplicationInfo""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.application_info.ApplicationInfo() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_authorization_api.py b/examples/demo9/python/mecapp/test/test_authorization_api.py new file mode 100644 index 000000000..d64a7a5d1 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_authorization_api.py @@ -0,0 +1,47 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.api.authorization_api import AuthorizationApi # noqa: E501 +from swagger_client.rest import ApiException + + +class TestAuthorizationApi(unittest.TestCase): + """AuthorizationApi unit test stubs""" + + def setUp(self): + self.api = AuthorizationApi() # noqa: E501 + + def tearDown(self): + pass + + def test_login(self): + """Test case for login + + Initiate OAuth login procedure and creates a MEC Sandbox instance # noqa: E501 + """ + pass + + def test_logout(self): + """Test case for logout + + Terminates User Session and delete the Sandbox instance # noqa: E501 + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_cellular_domain_config.py b/examples/demo9/python/mecapp/test/test_cellular_domain_config.py new file mode 100644 index 000000000..c849fa09c --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_cellular_domain_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.cellular_domain_config import CellularDomainConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestCellularDomainConfig(unittest.TestCase): + """CellularDomainConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCellularDomainConfig(self): + """Test CellularDomainConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.cellular_domain_config.CellularDomainConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_cellular_poa_config.py b/examples/demo9/python/mecapp/test/test_cellular_poa_config.py new file mode 100644 index 000000000..df61b5883 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_cellular_poa_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.cellular_poa_config import CellularPoaConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestCellularPoaConfig(unittest.TestCase): + """CellularPoaConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCellularPoaConfig(self): + """Test CellularPoaConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.cellular_poa_config.CellularPoaConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_connectivity_config.py b/examples/demo9/python/mecapp/test/test_connectivity_config.py new file mode 100644 index 000000000..d1f3600c9 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_connectivity_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.connectivity_config import ConnectivityConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestConnectivityConfig(unittest.TestCase): + """ConnectivityConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testConnectivityConfig(self): + """Test ConnectivityConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.connectivity_config.ConnectivityConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_cpu_config.py b/examples/demo9/python/mecapp/test/test_cpu_config.py new file mode 100644 index 000000000..67ad944a6 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_cpu_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.cpu_config import CpuConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestCpuConfig(unittest.TestCase): + """CpuConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCpuConfig(self): + """Test CpuConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.cpu_config.CpuConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_d2d_config.py b/examples/demo9/python/mecapp/test/test_d2d_config.py new file mode 100644 index 000000000..678cc5e6d --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_d2d_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.d2d_config import D2dConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestD2dConfig(unittest.TestCase): + """D2dConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testD2dConfig(self): + """Test D2dConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.d2d_config.D2dConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_deployment.py b/examples/demo9/python/mecapp/test/test_deployment.py new file mode 100644 index 000000000..e34d3f391 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_deployment.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.deployment import Deployment # noqa: E501 +from swagger_client.rest import ApiException + + +class TestDeployment(unittest.TestCase): + """Deployment unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testDeployment(self): + """Test Deployment""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.deployment.Deployment() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_dn_config.py b/examples/demo9/python/mecapp/test/test_dn_config.py new file mode 100644 index 000000000..cdfafdfee --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_dn_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.dn_config import DNConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestDNConfig(unittest.TestCase): + """DNConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testDNConfig(self): + """Test DNConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.dn_config.DNConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_domain.py b/examples/demo9/python/mecapp/test/test_domain.py new file mode 100644 index 000000000..556330859 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_domain.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.domain import Domain # noqa: E501 +from swagger_client.rest import ApiException + + +class TestDomain(unittest.TestCase): + """Domain unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testDomain(self): + """Test Domain""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.domain.Domain() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_egress_service.py b/examples/demo9/python/mecapp/test/test_egress_service.py new file mode 100644 index 000000000..caf8d8211 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_egress_service.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.egress_service import EgressService # noqa: E501 +from swagger_client.rest import ApiException + + +class TestEgressService(unittest.TestCase): + """EgressService unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testEgressService(self): + """Test EgressService""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.egress_service.EgressService() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_external_config.py b/examples/demo9/python/mecapp/test/test_external_config.py new file mode 100644 index 000000000..35b7cd7f8 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_external_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.external_config import ExternalConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestExternalConfig(unittest.TestCase): + """ExternalConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testExternalConfig(self): + """Test ExternalConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.external_config.ExternalConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_geo_data.py b/examples/demo9/python/mecapp/test/test_geo_data.py new file mode 100644 index 000000000..c82ebe27c --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_geo_data.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.geo_data import GeoData # noqa: E501 +from swagger_client.rest import ApiException + + +class TestGeoData(unittest.TestCase): + """GeoData unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testGeoData(self): + """Test GeoData""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.geo_data.GeoData() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_gpu_config.py b/examples/demo9/python/mecapp/test/test_gpu_config.py new file mode 100644 index 000000000..6dffcd931 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_gpu_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.gpu_config import GpuConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestGpuConfig(unittest.TestCase): + """GpuConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testGpuConfig(self): + """Test GpuConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.gpu_config.GpuConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_ingress_service.py b/examples/demo9/python/mecapp/test/test_ingress_service.py new file mode 100644 index 000000000..8e3a8bb6e --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_ingress_service.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.ingress_service import IngressService # noqa: E501 +from swagger_client.rest import ApiException + + +class TestIngressService(unittest.TestCase): + """IngressService unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testIngressService(self): + """Test IngressService""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.ingress_service.IngressService() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_line_string.py b/examples/demo9/python/mecapp/test/test_line_string.py new file mode 100644 index 000000000..cebe78224 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_line_string.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.line_string import LineString # noqa: E501 +from swagger_client.rest import ApiException + + +class TestLineString(unittest.TestCase): + """LineString unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testLineString(self): + """Test LineString""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.line_string.LineString() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_memory_config.py b/examples/demo9/python/mecapp/test/test_memory_config.py new file mode 100644 index 000000000..d260eef6b --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_memory_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.memory_config import MemoryConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestMemoryConfig(unittest.TestCase): + """MemoryConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testMemoryConfig(self): + """Test MemoryConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.memory_config.MemoryConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_network_characteristics.py b/examples/demo9/python/mecapp/test/test_network_characteristics.py new file mode 100644 index 000000000..aaa23a112 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_network_characteristics.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.network_characteristics import NetworkCharacteristics # noqa: E501 +from swagger_client.rest import ApiException + + +class TestNetworkCharacteristics(unittest.TestCase): + """NetworkCharacteristics unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testNetworkCharacteristics(self): + """Test NetworkCharacteristics""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.network_characteristics.NetworkCharacteristics() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_network_location.py b/examples/demo9/python/mecapp/test/test_network_location.py new file mode 100644 index 000000000..7a19b3bcc --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_network_location.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.network_location import NetworkLocation # noqa: E501 +from swagger_client.rest import ApiException + + +class TestNetworkLocation(unittest.TestCase): + """NetworkLocation unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testNetworkLocation(self): + """Test NetworkLocation""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.network_location.NetworkLocation() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_physical_location.py b/examples/demo9/python/mecapp/test/test_physical_location.py new file mode 100644 index 000000000..f9d4a2dec --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_physical_location.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.physical_location import PhysicalLocation # noqa: E501 +from swagger_client.rest import ApiException + + +class TestPhysicalLocation(unittest.TestCase): + """PhysicalLocation unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPhysicalLocation(self): + """Test PhysicalLocation""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.physical_location.PhysicalLocation() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_poa4_g_config.py b/examples/demo9/python/mecapp/test/test_poa4_g_config.py new file mode 100644 index 000000000..d41ef94e6 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_poa4_g_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.poa4_g_config import Poa4GConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestPoa4GConfig(unittest.TestCase): + """Poa4GConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPoa4GConfig(self): + """Test Poa4GConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.poa4_g_config.Poa4GConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_poa5_g_config.py b/examples/demo9/python/mecapp/test/test_poa5_g_config.py new file mode 100644 index 000000000..d5f6f2fe5 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_poa5_g_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.poa5_g_config import Poa5GConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestPoa5GConfig(unittest.TestCase): + """Poa5GConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPoa5GConfig(self): + """Test Poa5GConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.poa5_g_config.Poa5GConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_poa_wifi_config.py b/examples/demo9/python/mecapp/test/test_poa_wifi_config.py new file mode 100644 index 000000000..5a594ba0d --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_poa_wifi_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.poa_wifi_config import PoaWifiConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestPoaWifiConfig(unittest.TestCase): + """PoaWifiConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPoaWifiConfig(self): + """Test PoaWifiConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.poa_wifi_config.PoaWifiConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_point.py b/examples/demo9/python/mecapp/test/test_point.py new file mode 100644 index 000000000..91b69a5c4 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_point.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.point import Point # noqa: E501 +from swagger_client.rest import ApiException + + +class TestPoint(unittest.TestCase): + """Point unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPoint(self): + """Test Point""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.point.Point() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_problem_details.py b/examples/demo9/python/mecapp/test/test_problem_details.py new file mode 100644 index 000000000..8f0e1e962 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_problem_details.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.problem_details import ProblemDetails # noqa: E501 +from swagger_client.rest import ApiException + + +class TestProblemDetails(unittest.TestCase): + """ProblemDetails unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testProblemDetails(self): + """Test ProblemDetails""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.problem_details.ProblemDetails() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_process.py b/examples/demo9/python/mecapp/test/test_process.py new file mode 100644 index 000000000..4fc3188f1 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_process.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.process import Process # noqa: E501 +from swagger_client.rest import ApiException + + +class TestProcess(unittest.TestCase): + """Process unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testProcess(self): + """Test Process""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.process.Process() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox.py b/examples/demo9/python/mecapp/test/test_sandbox.py new file mode 100644 index 000000000..868d49d6a --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.sandbox import Sandbox # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandbox(unittest.TestCase): + """Sandbox unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testSandbox(self): + """Test Sandbox""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.sandbox.Sandbox() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_app_instances.py b/examples/demo9/python/mecapp/test/test_sandbox_app_instances.py new file mode 100644 index 000000000..7a245a5d8 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_app_instances.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.sandbox_app_instances import SandboxAppInstances # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxAppInstances(unittest.TestCase): + """SandboxAppInstances unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testSandboxAppInstances(self): + """Test SandboxAppInstances""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.sandbox_app_instances.SandboxAppInstances() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_app_instances_api.py b/examples/demo9/python/mecapp/test/test_sandbox_app_instances_api.py new file mode 100644 index 000000000..0df26e24b --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_app_instances_api.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.api.sandbox_app_instances_api import SandboxAppInstancesApi # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxAppInstancesApi(unittest.TestCase): + """SandboxAppInstancesApi unit test stubs""" + + def setUp(self): + self.api = SandboxAppInstancesApi() # noqa: E501 + + def tearDown(self): + pass + + def test_sandbox_app_instances_delete(self): + """Test case for sandbox_app_instances_delete + + Delete an existing application instance # noqa: E501 + """ + pass + + def test_sandbox_app_instances_get(self): + """Test case for sandbox_app_instances_get + + Get the list of the available application instance identifiers # noqa: E501 + """ + pass + + def test_sandbox_app_instances_post(self): + """Test case for sandbox_app_instances_post + + Create a new application instance identifier # noqa: E501 + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions.py b/examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions.py new file mode 100644 index 000000000..dfea77134 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.sandbox_logs_subscriptions import SandboxLogsSubscriptions # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxLogsSubscriptions(unittest.TestCase): + """SandboxLogsSubscriptions unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testSandboxLogsSubscriptions(self): + """Test SandboxLogsSubscriptions""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.sandbox_logs_subscriptions.SandboxLogsSubscriptions() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions_api.py b/examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions_api.py new file mode 100644 index 000000000..0b3d32c53 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_logs_subscriptions_api.py @@ -0,0 +1,47 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.api.sandbox_logs_subscriptions_api import SandboxLogsSubscriptionsApi # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxLogsSubscriptionsApi(unittest.TestCase): + """SandboxLogsSubscriptionsApi unit test stubs""" + + def setUp(self): + self.api = SandboxLogsSubscriptionsApi() # noqa: E501 + + def tearDown(self): + pass + + def test_sandbox_logs_subscriptions_delete(self): + """Test case for sandbox_logs_subscriptions_delete + + Subscription to receive logs from the sandbox # noqa: E501 + """ + pass + + def test_sandbox_logs_subscriptions_post(self): + """Test case for sandbox_logs_subscriptions_post + + Subscription to receive logs from the sandbox # noqa: E501 + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_mec_services.py b/examples/demo9/python/mecapp/test/test_sandbox_mec_services.py new file mode 100644 index 000000000..0414e33b1 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_mec_services.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.sandbox_mec_services import SandboxMecServices # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxMecServices(unittest.TestCase): + """SandboxMecServices unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testSandboxMecServices(self): + """Test SandboxMecServices""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.sandbox_mec_services.SandboxMecServices() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_mec_services_api.py b/examples/demo9/python/mecapp/test/test_sandbox_mec_services_api.py new file mode 100644 index 000000000..bdd52dff1 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_mec_services_api.py @@ -0,0 +1,40 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.api.sandbox_mec_services_api import SandboxMECServicesApi # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxMECServicesApi(unittest.TestCase): + """SandboxMECServicesApi unit test stubs""" + + def setUp(self): + self.api = SandboxMECServicesApi() # noqa: E501 + + def tearDown(self): + pass + + def test_sandbox_mec_services_get(self): + """Test case for sandbox_mec_services_get + + Get the list of the available MEC services # noqa: E501 + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_network_scenario.py b/examples/demo9/python/mecapp/test/test_sandbox_network_scenario.py new file mode 100644 index 000000000..5a62fb4ae --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_network_scenario.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.sandbox_network_scenario import SandboxNetworkScenario # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxNetworkScenario(unittest.TestCase): + """SandboxNetworkScenario unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testSandboxNetworkScenario(self): + """Test SandboxNetworkScenario""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.sandbox_network_scenario.SandboxNetworkScenario() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_network_scenarios_api.py b/examples/demo9/python/mecapp/test/test_sandbox_network_scenarios_api.py new file mode 100644 index 000000000..8a5378bb2 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_network_scenarios_api.py @@ -0,0 +1,61 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.api.sandbox_network_scenarios_api import SandboxNetworkScenariosApi # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxNetworkScenariosApi(unittest.TestCase): + """SandboxNetworkScenariosApi unit test stubs""" + + def setUp(self): + self.api = SandboxNetworkScenariosApi() # noqa: E501 + + def tearDown(self): + pass + + def test_sandbox_individual_network_scenarios_get(self): + """Test case for sandbox_individual_network_scenarios_get + + Get description of a Network Scenario to be used. # noqa: E501 + """ + pass + + def test_sandbox_network_scenario_delete(self): + """Test case for sandbox_network_scenario_delete + + Deactivate the Network Scenario. # noqa: E501 + """ + pass + + def test_sandbox_network_scenario_post(self): + """Test case for sandbox_network_scenario_post + + Selects the Network Scenario to be activated. # noqa: E501 + """ + pass + + def test_sandbox_network_scenarios_get(self): + """Test case for sandbox_network_scenarios_get + + Get the list of the available network scenarios # noqa: E501 + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_sandbox_ue_controller_api.py b/examples/demo9/python/mecapp/test/test_sandbox_ue_controller_api.py new file mode 100644 index 000000000..56ae047e4 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_sandbox_ue_controller_api.py @@ -0,0 +1,47 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.api.sandbox_ue_controller_api import SandboxUEControllerApi # noqa: E501 +from swagger_client.rest import ApiException + + +class TestSandboxUEControllerApi(unittest.TestCase): + """SandboxUEControllerApi unit test stubs""" + + def setUp(self): + self.api = SandboxUEControllerApi() # noqa: E501 + + def tearDown(self): + pass + + def test_sandbox_ue_controller_get(self): + """Test case for sandbox_ue_controller_get + + Get the list of the available UEs (e.g. \"Stationary UE\") # noqa: E501 + """ + pass + + def test_sandbox_ue_controller_patch(self): + """Test case for sandbox_ue_controller_patch + + set the new value of the UE # noqa: E501 + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_scenario.py b/examples/demo9/python/mecapp/test/test_scenario.py new file mode 100644 index 000000000..ca7fb93f3 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_scenario.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.scenario import Scenario # noqa: E501 +from swagger_client.rest import ApiException + + +class TestScenario(unittest.TestCase): + """Scenario unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testScenario(self): + """Test Scenario""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.scenario.Scenario() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_scenario_config.py b/examples/demo9/python/mecapp/test/test_scenario_config.py new file mode 100644 index 000000000..47bc7378d --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_scenario_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.scenario_config import ScenarioConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestScenarioConfig(unittest.TestCase): + """ScenarioConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testScenarioConfig(self): + """Test ScenarioConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.scenario_config.ScenarioConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_service_config.py b/examples/demo9/python/mecapp/test/test_service_config.py new file mode 100644 index 000000000..e9101a2b5 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_service_config.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.service_config import ServiceConfig # noqa: E501 +from swagger_client.rest import ApiException + + +class TestServiceConfig(unittest.TestCase): + """ServiceConfig unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testServiceConfig(self): + """Test ServiceConfig""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.service_config.ServiceConfig() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_service_port.py b/examples/demo9/python/mecapp/test/test_service_port.py new file mode 100644 index 000000000..2dd9c79d7 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_service_port.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.service_port import ServicePort # noqa: E501 +from swagger_client.rest import ApiException + + +class TestServicePort(unittest.TestCase): + """ServicePort unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testServicePort(self): + """Test ServicePort""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.service_port.ServicePort() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_ue.py b/examples/demo9/python/mecapp/test/test_ue.py new file mode 100644 index 000000000..8f2c51854 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_ue.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.ue import UE # noqa: E501 +from swagger_client.rest import ApiException + + +class TestUE(unittest.TestCase): + """UE unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testUE(self): + """Test UE""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.ue.UE() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/test/test_zone.py b/examples/demo9/python/mecapp/test/test_zone.py new file mode 100644 index 000000000..3bf14c506 --- /dev/null +++ b/examples/demo9/python/mecapp/test/test_zone.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +""" + MEC Sandbox API + + The MEC Sandbox API described using OpenAPI # noqa: E501 + + OpenAPI spec version: 0.0.7 + Contact: cti_support@etsi.org + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + +from __future__ import absolute_import + +import unittest + +import swagger_client +from swagger_client.models.zone import Zone # noqa: E501 +from swagger_client.rest import ApiException + + +class TestZone(unittest.TestCase): + """Zone unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testZone(self): + """Test Zone""" + # FIXME: construct object with mandatory attributes with example values + # model = swagger_client.models.zone.Zone() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/demo9/python/mecapp/tox.ini b/examples/demo9/python/mecapp/tox.ini new file mode 100644 index 000000000..a310bec97 --- /dev/null +++ b/examples/demo9/python/mecapp/tox.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv] +deps=-r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +commands= + nosetests \ + [] diff --git a/examples/demo9/python/notebook/MEC_And_oneM2M_Tutorial.ipynb b/examples/demo9/python/notebook/MEC_And_oneM2M_Tutorial.ipynb new file mode 100644 index 000000000..af032a920 --- /dev/null +++ b/examples/demo9/python/notebook/MEC_And_oneM2M_Tutorial.ipynb @@ -0,0 +1,3765 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# How to develop an ETSI MEC application to exploit both ETSI MEC and oneM2M platforms\n", + "This tutorial introduces the step by step procedure to create a basic MEC application following ETSI MEC standards and oneM2M standards to manage devices/sensors/actuators...\n", + "It uses the ETSI MEC Sandbox simulator.\n", + "\n", + "
    \n", + " Note: These source code examples are simplified and ignore return codes and error checks to a large extent. We do this to highlight how to use the MEC Sandbox API and the different MEC satndards and reduce unrelated code.\n", + "A real-world application will of course properly check every return value and exit correctly at the first serious error.\n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What is a ETSI MEC application\n", + "\n", + "For more details on how to develop an ETSI MEC application, please refer to [The Wiki MEC web site](https://www.etsi.org/technologies/multi-access-edge-computing) and the [ETSI MEC Tutoral](http://mec-platform2.etsi.org:9999/notebooks/work/notebook/MEC%20application.ipynb).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The basics to develop an ETSI MEC application\n", + "\n", + "All the code below are helpers functions required to start the development our MEC application.\n", + "\n", + "
    \n", + " Note: The sub-paragraph 'Putting everything together' is a specific paragraph where all the newly features introduced in the main paragraph are put together to create an executable block of code. It is possible to skip this block of code by removing the comment character (#) on first line of this block of code.\n", + "
    \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import os\n", + "os.chdir(os.path.join(os.getcwd(), '../mecapp'))\n", + "print(os.getcwd())\n", + "from __future__ import division # Import floating-point division (1/4=0.25) instead of Euclidian division (1/4=0)\n", + "\n", + "import os\n", + "import sys\n", + "import re\n", + "import logging\n", + "import threading\n", + "import time\n", + "import json\n", + "import uuid\n", + "\n", + "import pprint\n", + "\n", + "import six\n", + "\n", + "import swagger_client\n", + "from swagger_client.rest import ApiException\n", + "\n", + "from http import HTTPStatus\n", + "from http.server import BaseHTTPRequestHandler, HTTPServer\n", + "\n", + "try:\n", + " import urllib3\n", + "except ImportError:\n", + " raise ImportError('Swagger python client requires urllib3.')\n", + "\n", + "MEC_SANDBOX_URL = 'https://mec-platform.etsi.org' # MEC Sandbox host/base URL\n", + "MEC_SANDBOX_API_URL = 'https://mec-platform.etsi.org/sandbox-api/v1' # MEC Sandbox API host/base URL\n", + "PROVIDER = 'Jupyter2024' # Login provider value - To skip authorization: 'github'\n", + "MEC_PLTF = 'mep1' # MEC plateform name. Linked to the network scenario\n", + "LOGGER_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # Logging format\n", + "STABLE_TIME_OUT = 10 # Timer to wait for MEC Sndbox reaches its stable state (K8S pods in running state)\n", + "LOGIN_TIMEOUT = 3 #30 # Timer to wait for user to authorize from GITHUB\n", + "LISTENER_IP = '0.0.0.0' # Listener IPv4 address for notification callback calls\n", + "LISTENER_PORT = 31111 # Listener IPv4 port for notification callback calls. Default: 36001\n", + "CALLBACK_URI = 'http://mec-platform.etsi.org:31111/sandbox/v1'\n", + " #'https://yanngarcia.ddns.net:' + str(LISTENER_PORT) + '/jupyter/sandbox/demo6/v1/'\n", + "# Initialize the logger\n", + "logger = logging.getLogger(__name__)\n", + "logger.setLevel(logging.DEBUG)\n", + "logging.basicConfig(filename='/tmp/' + time.strftime('%Y%m%d-%H%M%S') + '.log')\n", + "l = logging.StreamHandler()\n", + "l.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))\n", + "logger.addHandler(l)\n", + "\n", + "# Setup the HTTP REST API configuration to be used to send request to MEC Sandbox API \n", + "configuration = swagger_client.Configuration()\n", + "configuration.host = MEC_SANDBOX_API_URL\n", + "configuration.verify_ssl = True\n", + "configuration.debug = True\n", + "configuration.logger_format = LOGGER_FORMAT\n", + "\n", + "# Create an instance of ApiClient\n", + "sandbox_api = swagger_client.ApiClient(configuration, 'Content-Type', 'application/json')\n", + "\n", + "# Setup the HTTP REST API configuration to be used to send request to MEC Services\n", + "configuration1 = swagger_client.Configuration()\n", + "configuration1.host = MEC_SANDBOX_URL\n", + "configuration1.verify_ssl = True\n", + "configuration1.debug = True\n", + "configuration1.logger_format = LOGGER_FORMAT\n", + "\n", + "# Create an instance of ApiClient\n", + "service_api = swagger_client.ApiClient(configuration1, 'Content-Type', 'application/json')\n", + "\n", + "# Initialize the global variables\n", + "nw_scenarios = [] # The list of available network scenarios\n", + "nw_scenario_idx = -1 # The network scenario idx to activate (deactivate)\n", + "app_inst_id = None # The requested application instance identifier\n", + "got_notification = False # Set to true if a POST notification is received\n", + "\n", + "# Login\n", + "def process_login() -> str:\n", + " \"\"\"\n", + " Authenticate and create a new MEC Sandbox instance.\n", + " :return: The sandbox instance identifier on success, None otherwise\n", + " \"\"\" \n", + " global PROVIDER, logger\n", + "\n", + " logger.debug('>>> process_login')\n", + "\n", + " try:\n", + " auth = swagger_client.AuthorizationApi(sandbox_api)\n", + " oauth = auth.login(PROVIDER, async_req = False)\n", + " logger.debug('process_login (step1): oauth: ' + str(oauth))\n", + " # Wait for the MEC Sandbox is running\n", + " logger.debug('=======================> DO AUTHORIZATION WITH CODE : ' + oauth.user_code)\n", + " logger.debug('=======================> DO AUTHORIZATION HERE : ' + oauth.verification_uri)\n", + " if oauth.verification_uri == \"\":\n", + " time.sleep(LOGIN_TIMEOUT) # Skip scecurity, wait for a few seconds\n", + " else:\n", + " time.sleep(10 * LOGIN_TIMEOUT) # Wait for Authirization from user side\n", + " namespace = auth.get_namespace(oauth.user_code)\n", + " logger.debug('process_login (step2): result: ' + str(namespace))\n", + " return namespace.sandbox_name\n", + " except ApiException as e:\n", + " logger.error('Exception when calling AuthorizationApi->login: %s\\n' % e)\n", + "\n", + " return None\n", + " # End of function process_login\n", + "\n", + "# Logout\n", + "def process_logout(sandbox_name: str) -> int:\n", + " \"\"\"\n", + " Delete the specified MEC Sandbox instance.\n", + " :param sandbox_name: The MEC Sandbox to delete\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global logger\n", + "\n", + " logger.debug('>>> process_logout: sandbox=' + sandbox_name)\n", + "\n", + " try:\n", + " auth = swagger_client.AuthorizationApi(sandbox_api)\n", + " result = auth.logout(sandbox_name, async_req = False) # noqa: E501\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling AuthorizationApi->logout: %s\\n' % e)\n", + " return -1\n", + " # End of function process_logout\n", + "\n", + "\n", + "def get_network_scenarios(sandbox_name: str) -> list:\n", + " \"\"\"\n", + " Retrieve the list of the available network scenarios.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return: The list of the available network scenarios on success, None otherwise\n", + " \"\"\"\n", + " global PROVIDER, logger, sandbox_api, configuration\n", + "\n", + " logger.debug('>>> get_network_scenarios: sandbox=' + sandbox_name)\n", + "\n", + " try:\n", + " nw = swagger_client.SandboxNetworkScenariosApi(sandbox_api)\n", + " result = nw.sandbox_network_scenarios_get(sandbox_name, async_req = False) # noqa: E501\n", + " logger.debug('get_network_scenarios: result: ' + str(result))\n", + " return result\n", + " except ApiException as e:\n", + " logger.error('Exception when calling SandboxNetworkScenariosApi->sandbox_network_scenarios_get: %s\\n' % e)\n", + "\n", + " return None\n", + " # End of function get_network_scenarios\n", + "\n", + "def select_network_scenario_based_on_criteria(criterias_list: list) -> int:\n", + " \"\"\"\n", + " Select the network scenario to activate based of the provided list of criterias.\n", + " :param criterias_list: The list of criterias to select the correct network scenario\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + "\n", + " return 0 # The index of the '4g-5g-macro-v2x' network scenario - Hard coded\n", + "def activate_network_scenario(sandbox_name: str) -> int:\n", + " \"\"\"\n", + " Activate the specified network scenario.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global logger, sandbox_api, nw_scenarios, nw_scenario_idx\n", + "\n", + " logger.debug('>>> activate_network_scenario: ' + sandbox_name)\n", + "\n", + " nw_scenario_idx = select_network_scenario_based_on_criteria([])\n", + " if nw_scenario_idx == -1:\n", + " logger.error('activate_network_scenario: Failed to select a network scenarion')\n", + " return -1\n", + "\n", + " try:\n", + " nw = swagger_client.SandboxNetworkScenariosApi(sandbox_api)\n", + " nw.sandbox_network_scenario_post(sandbox_name, nw_scenarios[nw_scenario_idx].id, async_req = False) # noqa: E501\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling SandboxNetworkScenariosApi->activate_network_scenario: %s\\n' % e)\n", + "\n", + " return -1\n", + " # End of function activate_network_scenario\n", + "\n", + "def deactivate_network_scenario(sandbox: str) -> int:\n", + " \"\"\"\n", + " Deactivate the current network scenario.\n", + " :param sandbox: The MEC Sandbox instance to use\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global logger, sandbox_api, nw_scenarios, nw_scenario_idx\n", + "\n", + " logger.debug('>>> deactivate_network_scenario: ' + sandbox)\n", + "\n", + " try:\n", + " nw = swagger_client.SandboxNetworkScenariosApi(sandbox_api)\n", + " nw.sandbox_network_scenario_delete(sandbox, nw_scenarios[nw_scenario_idx].id, async_req = False) # noqa: E501\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling SandboxNetworkScenariosApi->deactivate_network_scenario: %s\\n' % e)\n", + "\n", + " return -1\n", + " # End of function deactivate_network_scenario\n", + "\n", + "def request_application_instance_id(sandbox_name: str) -> swagger_client.models.ApplicationInfo:\n", + " \"\"\"\n", + " Request the creation of a new MEC application instance identifier.\n", + " It is like the MEC application was instanciated by the MEC platform and it is executed locally.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return: The MEC application instance identifier on success, None otherwise\n", + " :see ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.2 MEC application start-up\n", + " \"\"\"\n", + " global MEC_PLTF, logger, sandbox_api, configuration\n", + "\n", + " logger.debug('>>> request_application_instance_id: ' + sandbox_name)\n", + "\n", + " # Create a instance of our MEC application\n", + " try:\n", + " a = swagger_client.models.ApplicationInfo(id=str(uuid.uuid4()), name='JupyterMecApp', node_name=MEC_PLTF, type='USER') # noqa: E501\n", + " nw = swagger_client.SandboxAppInstancesApi(sandbox_api)\n", + " result = nw.sandbox_app_instances_post(a, sandbox_name, async_req = False) # noqa: E501\n", + " logger.debug('request_application_instance_id: result: ' + str(result))\n", + " return result\n", + " except ApiException as e:\n", + " logger.error('Exception when calling SandboxAppInstancesApi->sandbox_app_instances_post: %s\\n' % e)\n", + "\n", + " return None\n", + " # End of function request_application_instance_id\n", + "def delete_application_instance_id(sandbox_name: str, app_inst_id: str) -> int:\n", + " \"\"\"\n", + " Request the deletion of a MEC application.\n", + " :param sandbox: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global logger, sandbox_api, configuration\n", + "\n", + " logger.debug('>>> delete_application_instance_id: ' + sandbox_name)\n", + " logger.debug('>>> delete_application_instance_id: ' + app_inst_id)\n", + "\n", + " try:\n", + " nw = swagger_client.SandboxAppInstancesApi(sandbox_api)\n", + " nw.sandbox_app_instances_delete(sandbox_name, app_inst_id, async_req = False) # noqa: E501\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling SandboxAppInstancesApi->sandbox_app_instances_delete: %s\\n' % e)\n", + "\n", + " return -1\n", + " # End of function deletet_application_instance_id\n", + "def get_applications_list(sandbox_name: str) -> list:\n", + " \"\"\"\n", + " Request the list of the MEC application available on the MEC Platform.\n", + " :param sandbox: The MEC Sandbox instance to use\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global logger, sandbox_api, configuration\n", + "\n", + " logger.debug('>>> get_applications_list: ' + sandbox_name)\n", + "\n", + " try:\n", + " nw = swagger_client.SandboxAppInstancesApi(sandbox_api)\n", + " result = nw.sandbox_app_instances_get(sandbox_name, async_req = False) # noqa: E501\n", + " logger.debug('get_applications_list: result: ' + str(result))\n", + " return result\n", + " except ApiException as e:\n", + " logger.error('Exception when calling SandboxAppInstancesApi->get_applications_list: %s\\n' % e)\n", + " return None \n", + " # End of function delete_application_instance_id\n", + "def send_ready_confirmation(sandbox_name: str, app_inst_id: swagger_client.models.application_info.ApplicationInfo) -> int:\n", + " \"\"\"\n", + " Send the ready_confirmation to indicate that the MEC application is active.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :return: 0 on success, -1 otherwise\n", + " :see ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.2 MEC application start-up - Step 4c\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> send_ready_confirmation: ' + app_inst_id.id)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/mec_app_support/v2/applications/{app_inst_id}/confirm_ready'\n", + " logger.debug('send_ready_confirmation: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " path_params['app_inst_id'] = app_inst_id.id\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " # JSON indication READY\n", + " dict_body = {}\n", + " dict_body['indication'] = 'READY'\n", + " service_api.call_api(url, 'POST', header_params=header_params, path_params = path_params, body=dict_body, async_req=False)\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return -1\n", + " # End of function send_ready_confirmation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def send_subscribe_termination(sandbox_name: str, app_inst_id: swagger_client.models.application_info.ApplicationInfo) -> object:\n", + " \"\"\"\n", + " Subscribe to the MEC application termination notifications.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :return: The HTTP respone, the subscription ID and the resource URL on success, None otherwise\n", + " :see ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.6b Receiving event notifications on MEC application instance termination\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> send_subscribe_termination: ' + app_inst_id.id)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/mec_app_support/v2/applications/{app_inst_id}/subscriptions'\n", + " logger.debug('send_subscribe_termination: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " path_params['app_inst_id'] = app_inst_id.id\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " # Body\n", + " dict_body = {}\n", + " dict_body['subscriptionType'] = 'AppTerminationNotificationSubscription'\n", + " dict_body['callbackReference'] = CALLBACK_URI + '/mec011/v2/termination' # FIXME To be parameterized\n", + " dict_body['appInstanceId'] = app_inst_id.id\n", + " (result, status, headers) = service_api.call_api(url, 'POST', header_params=header_params, path_params = path_params, body=dict_body, async_req=False)\n", + " return (result, extract_sub_id(headers['Location']), headers['Location'])\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status, None)\n", + " # End of function send_subscribe_termination\n", + "def extract_sub_id(resource_url: str) -> str:\n", + " \"\"\"\n", + " Extract the subscription identifier from the specified subscription URL.\n", + " :param resource_url: The subscription URL\n", + " :return: The subscription identifier on success, None otherwise\n", + " \"\"\"\n", + " global logger\n", + "\n", + " logger.debug('>>> extract_sub_id: resource_url: ' + resource_url)\n", + "\n", + " res = urllib3.util.parse_url(resource_url)\n", + " if res is not None and res.path is not None and res.path != '':\n", + " id = res.path.rsplit('/', 1)[-1]\n", + " if id is not None:\n", + " return id\n", + " return None\n", + " # End of function extract_sub_id\n", + "def delete_subscribe_termination(sandbox_name: str, app_inst_id: swagger_client.models.application_info.ApplicationInfo, sub_id: str) -> int:\n", + " \"\"\"\n", + " Delete the subscrition to the AppTermination notification.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :param sub_id: The subscription identifier\n", + " :return: 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> delete_subscribe_termination: ' + app_inst_id.id)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/mec_app_support/v2/applications/{app_inst_id}/subscriptions/{sub_id}'\n", + " logger.debug('delete_subscribe_termination: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " path_params['app_inst_id'] = app_inst_id.id\n", + " path_params['sub_id'] = sub_id\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " service_api.call_api(url, 'DELETE', header_params=header_params, path_params = path_params, async_req=False)\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return -1\n", + " # End of function delete_subscribe_termination\n", + "def send_termination_confirmation(sandbox_name: str, app_inst_id: swagger_client.models.application_info.ApplicationInfo) -> int:\n", + " \"\"\"\n", + " Send the confirm_termination to indicate that the MEC application is terminating gracefully.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :return: 0 on success, -1 otherwise\n", + " :see ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.3 MEC application graceful termination/stop\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> send_termination_confirmation: ' + app_inst_id.id)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/mec_app_support/v2/applications/{app_inst_id}/confirm_termination'\n", + " logger.debug('send_termination_confirmation: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " path_params['app_inst_id'] = app_inst_id.id\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " # JSON indication READY\n", + " dict_body = {}\n", + " dict_body['operationAction'] = 'TERMINATING'\n", + " service_api.call_api(url, 'POST', header_params=header_params, path_params = path_params, body=dict_body, async_req=False)\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return -1\n", + " # End of function send_termination_confirmation\n", + "def mec_app_setup():\n", + " \"\"\"\n", + " This function provides the steps to setup a MEC application:\n", + " - Login\n", + " - Print sandbox identifier\n", + " - Print available network scenarios\n", + " - Activate a network scenario\n", + " - Request for a new application instance identifier\n", + " - Send READY confirmation\n", + " - Subscribe to AppTermination Notification\n", + " :return The MEC Sandbox instance, the MEC application instance identifier and the subscription identifier on success, None otherwise\n", + " \"\"\"\n", + " global logger, nw_scenarios\n", + "\n", + " # Login\n", + " sandbox = process_login()\n", + " if sandbox is None:\n", + " logger.error('Failed to instanciate a MEC Sandbox')\n", + " return None\n", + " # Wait for the MEC Sandbox is running\n", + " time.sleep(STABLE_TIME_OUT) # Wait for k8s pods up and running\n", + "\n", + " # Print available network scenarios\n", + " nw_scenarios = get_network_scenarios(sandbox)\n", + " if nw_scenarios is None:\n", + " logger.error('Failed to retrieve the list of network scenarios')\n", + " elif len(nw_scenarios) != 0:\n", + " # Wait for the MEC Sandbox is running\n", + " time.sleep(STABLE_TIME_OUT) # Wait for k8s pods up and running\n", + " else:\n", + " logger.info('nw_scenarios: No scenario available')\n", + "\n", + " # Activate a network scenario based on a list of criterias (hard coded!!!)\n", + " if activate_network_scenario(sandbox) == -1:\n", + " logger.error('Failed to activate network scenario')\n", + " else:\n", + " # Wait for the MEC services are running\n", + " time.sleep(2 * STABLE_TIME_OUT) # Wait for k8s pods up and running\n", + "\n", + " # Request for a new application instance identifier\n", + " app_inst_id = request_application_instance_id(sandbox)\n", + " if app_inst_id == None:\n", + " logger.error('Failed to request an application instance identifier')\n", + " else:\n", + " # Wait for the MEC services are terminated\n", + " time.sleep(STABLE_TIME_OUT)\n", + "\n", + " # Send READY confirmation\n", + " sub_id = None\n", + " if send_ready_confirmation(sandbox, app_inst_id) == -1:\n", + " logger.error('Failed to send confirm_ready')\n", + " else:\n", + " # Subscribe to AppTerminationNotificationSubscription\n", + " result, sub_id, res_url = send_subscribe_termination(sandbox, app_inst_id)\n", + " if sub_id == None:\n", + " logger.error('Failed to do the subscription')\n", + "\n", + " return (sandbox, app_inst_id, sub_id)\n", + " # End of function mec_app_setup\n", + "def mec_app_termination(sandbox_name: str, app_inst_id:swagger_client.models.ApplicationInfo, sub_id: str):\n", + " \"\"\"\n", + " This function provides the steps to setup a MEC application:\n", + " - Login\n", + " - Print sandbox identifier\n", + " - Print available network scenarios\n", + " - Activate a network scenario\n", + " - Request for a new application instance identifier\n", + " - Send READY confirmation\n", + " - Subscribe to AppTermination Notification\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :param sub_id: The subscription identifier\n", + " \"\"\"\n", + " global logger\n", + "\n", + " # Delete AppTerminationNotification subscription\n", + " if sub_id is not None:\n", + " if delete_subscribe_termination(sandbox_name, app_inst_id, sub_id) == -1:\n", + " logger.error('Failed to delete the application instance identifier')\n", + "\n", + " # Delete the application instance identifier\n", + " if delete_application_instance_id(sandbox_name, app_inst_id.id) == -1:\n", + " logger.error('Failed to delete the application instance identifier')\n", + " else:\n", + " # Wait for the MEC services are terminated\n", + " time.sleep(STABLE_TIME_OUT)\n", + "\n", + " # Deactivate a network scenario based on a list of criterias (hard coded!!!)\n", + " if deactivate_network_scenario(sandbox_name) == -1:\n", + " logger.error('Failed to deactivate network scenario')\n", + " else:\n", + " # Wait for the MEC services are terminated\n", + " time.sleep(2 * STABLE_TIME_OUT)\n", + "\n", + " # Logout\n", + " process_logout(sandbox_name)\n", + " # End of function mec_app_termination" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create our first ETSI MEC application: wait for the oneM2M platform to register to the ETSI MEC platform\n", + "\n", + "Here, we just going to poll every 5 seconds to verify if the oneM2M platform is regieterd. After one minutes this function returns with than error.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def check_is_om2m_platform_registered(sandbox_name: str) -> int:\n", + " \"\"\"\n", + " To retrieves the location information of an UE identified by its IPv4 address (e.g. 10.100.0.1)\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return The oneM2M platform identifier on success, None otherwise\n", + " :see ETSI GS MEC 033 V3.1.1 (2022-12) Clause 5.3.2 Registered IoT platforms query\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> check_is_om2m_platform_registered')\n", + " expiry = 0\n", + " while expiry < 60: # one minute\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/iot/v1/queries/iot_platform'\n", + " logger.debug('check_is_om2m_platform_registered: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " (result, status, headers) = service_api.call_api(url, 'GET', header_params=header_params, path_params=path_params, async_req=False)\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return -1\n", + " if status == 200:\n", + " # Extract the oneM2M platform identifier\n", + " return 0\n", + " expiry += 10\n", + " time.sleep(10) # Wait for 5 seconds \n", + " # End of 'while' statement\n", + " # End of function check_is_om2m_platform_registered" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Putting everything together\n", + "\n", + "It is time now to create the our third iteration of our ETSI MEC application.\n", + "\n", + "The sequence is the following:\n", + "- Create an ETSI MEC application instance\n", + "- Wait for a oneM2M platform to register to the ETSI MEC platform\n", + "- Display the oneM2M platform identifier\n", + "- Terminate the ETSI MEC application instance" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the second sprint of our skeleton of our MEC application:\n", + " - Create an ETSI MEC application instance\n", + " - Wait for a oneM2M platform to register to the ETSI MEC platform (1 minute max.)\n", + " - Display the oneM2M platform identifier\n", + " - Terminate the ETSI MEC application instance\n", + " \"\"\" \n", + " global logger, nw_scenarios\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Setup the MEC application\n", + " (sandbox_name, app_inst_id, sub_id) = mec_app_setup()\n", + "\n", + " # Wait for a oneM2M platform to register to the ETSI MEC platform\n", + " om2m_pltf_id = check_is_om2m_platform_registered(sandbox_name)\n", + " if not om2m_pltf_id is None:\n", + " logger.info('om2m_pltf_id: %s', str(om2m_pltf_id))\n", + " else:\n", + " logger.info('Timeout')\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Second step: Adding a subscription\n", + "\n", + "The purpose here is to create a subscritpion when the UE (e.g. 10.100.0.1) is entering or leaving a PoA area (PoA is tanding for Piont of Access).\n", + "Accorcding to ETSI GS MEC 013 V3.1.1 Clause 7.5.3.4 POST, the 'request method is a POST and the endpoint is '/location/v3/subscriptions/users/'.\n", + "\n", + "The cell below provides the code to create our subscription." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Notification support\n", + "\n", + "To recieve notification, our MEC application is required to support an HTTP listenener to recieve POST requests from the MEC Sandbox and reply to them: this is the notification mechanism.\n", + "\n", + "This minimalistic HTTP server will also be used to implement the endpoints provided by our MEC application service: see chapter [Our third MEC application: how to create a new MEC Services](#our_third_mec_application_how_to_create_a_new_mec_services).\n", + "\n", + "The class HTTPRequestHandler (see cell below) provides the suport of such mechanism.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class HTTPServer_RequestHandler(BaseHTTPRequestHandler):\n", + " \"\"\"\n", + " Minimal implementation of an HTTP server (http only).\n", + " \"\"\"\n", + "\n", + " def do_GET(self):\n", + " logger.info('>>> do_GET: ' + self.path)\n", + "\n", + " ctype = self.headers.get('content-type')\n", + " logger.info('do_GET: ' + ctype)\n", + "\n", + " message = ''\n", + " if self.path == '/sandbox/v1/statistic/v1/quantity':\n", + " logger.info('do_GET: Computing statistic quantities for application MEC service')\n", + " # TODO Add logit to our MEC service\n", + " message = '{\"time\":20180124,\"avg\": 0.0,\"max\": 0.0,\"min\": 0.0,\"stddev\": 0.0 }'\n", + " else:\n", + " # Send error message\n", + " message = '{\"title\":\"Unknown URI\",\"type\":\"do_GET.parser\",\"status\":404 }'\n", + " logger.info('do_GET: message: ' + message)\n", + " \n", + " # Send response status code\n", + " self.send_response(HTTPStatus.OK)\n", + "\n", + " # Send headers\n", + " self.send_header('Content-type','text/plain; charset=utf-8')\n", + " self.send_header('Content-length', str(len(message)))\n", + " self.end_headers()\n", + "\n", + " # Write content as utf-8 data\n", + " self.wfile.write(message.encode('utf8'))\n", + " return\n", + " # End of function do_GET\n", + "\n", + " def do_POST(self):\n", + " global got_notification\n", + "\n", + " logger.info('>>> do_POST: ' + self.path)\n", + "\n", + " ctype = self.headers.get('content-type')\n", + " logger.info('do_POST: ' + ctype)\n", + "\n", + " content_len = int(self.headers.get('Content-Length'))\n", + " if content_len != 0:\n", + " body = self.rfile.read(content_len).decode('utf8')\n", + " logger.info('do_POST: body:' + str(type(body)))\n", + " logger.info('do_POST: body:' + str(body))\n", + " data = json.loads(str(body))\n", + " logger.info('do_POST: data: %s', str(data))\n", + "\n", + " self.send_response(HTTPStatus.NOT_IMPLEMENTED)\n", + " self.end_headers()\n", + " got_notification = True\n", + " return\n", + " # End of function do_POST\n", + "\n", + " def do_PUT(self):\n", + " logger.info('>>> do_PUT: ' + self.path)\n", + "\n", + " ctype = self.headers.get('content-type')\n", + " logger.info('do_PUT: ' + ctype)\n", + "\n", + " self.send_response(HTTPStatus.NOT_IMPLEMENTED)\n", + " self.end_headers()\n", + " return\n", + " # End of function do_PUT\n", + "\n", + " def do_PATCH(self):\n", + " logger.info('>>> do_PATCH: ' + self.path)\n", + "\n", + " ctype = self.headers.get('content-type')\n", + " logger.info('do_PATCH: ' + ctype)\n", + " \n", + " self.send_response(HTTPStatus.NOT_IMPLEMENTED)\n", + " self.end_headers()\n", + " return\n", + " # End of function do_PATCH\n", + " # End of class HTTPRequestHandler\n", + "\n", + " def do_DELETE(self):\n", + " logger.info('>>> do_DELETE: ' + self.path)\n", + "\n", + " ctype = self.headers.get('content-type')\n", + " logger.info('do_DELETE: ' + ctype)\n", + " \n", + " self.send_response(HTTPStatus.NOT_IMPLEMENTED)\n", + " self.end_headers()\n", + " return\n", + " # End of function do_DELETE\n", + " # End of class HTTPRequestHandler\n", + "\n", + "def start_notification_server() -> HTTPServer:\n", + " \"\"\"\n", + " Start the notification server\n", + " :return The instance of the HTTP server\n", + " \"\"\"\n", + " global LISTENER_PORT, got_notification, logger\n", + "\n", + " logger.debug('>>> start_notification_server on port ' + str(LISTENER_PORT))\n", + " got_notification = False\n", + " server_address = ('', LISTENER_PORT)\n", + " httpd = HTTPServer(server_address, HTTPServer_RequestHandler)\n", + " # Start notification server in a daemonized thread\n", + " notification_server = threading.Thread(target = httpd.serve_forever, name='notification_server')\n", + " notification_server.daemon = True\n", + " notification_server.start()\n", + " return httpd\n", + " # End of function HTTPRequestHandler\n", + "\n", + "def stop_notification_server(httpd: HTTPServer):\n", + " \"\"\"\n", + " Stop the notification server\n", + " :param The instance of the HTTP server\n", + " \"\"\"\n", + " global logger\n", + "\n", + " logger.debug('>>> stop_notification_server')\n", + " httpd.server_close()\n", + " httpd=None\n", + " # End of function HTTPRequestHandler\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def subscribe_for_user_events(sandbox_name: str) -> object:\n", + " \"\"\"\n", + " Subscriptions for notifications related to location.\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return: The HTTP respone, the subscription ID and the resource URL on success, None otherwise\n", + " :see ETSI GS MEC 013 V3.1.1 Clause 7.5 Resource: user_subscriptions\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> subscribe_for_user_events: ' + sandbox_name)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}//location/v3/subscriptions/users'\n", + " logger.debug('subscribe_for_user_events: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " # Body\n", + " dict_body = {}\n", + " dict_body['subscriptionType'] = 'UserLocationEventSubscription'\n", + " dict_body['callbackReference'] = CALLBACK_URI + '/mec013/v3/location' # FIXME To be parameterized\n", + " dict_body['address'] = '10.100.0.1' # FIXME To be parameterized\n", + " dict_body['clientCorrelator'] = \"12345\"\n", + " dict_body['locationEventCriteria'] = [ \"ENTERING_AREA_EVENT\", \"LEAVING_AREA_EVENT\"]\n", + " m = {}\n", + " m[\"userLocationEventSubscription\"] = dict_body\n", + " (result, status, headers) = service_api.call_api(url, 'POST', header_params=header_params, path_params = path_params, body=m, async_req=False)\n", + " return (result, extract_sub_id(headers['Location']), headers['Location'])\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, None, None)\n", + " # End of function subscribe_for_user_are_event" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Putting everything together\n", + "\n", + "It is time now to create the our third iteration of our MEC application.\n", + "\n", + "The sequence is the following:\n", + "- Login\n", + "- Activate a network scenario\n", + "- Create subscription\n", + "- Wait for notification\n", + "- Delete our application instance identifier\n", + "- Deactivate a network scenario\n", + "- Logout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the second sprint of our skeleton of our MEC application:\n", + " - Login\n", + " - Activate a network scenario\n", + " - Create subscription\n", + " - Wait for notification\n", + " - Delete our application instance identifier\n", + " - Deactivate a network scenario\n", + " - Logout\n", + " \"\"\" \n", + " global logger, nw_scenarios, got_notification\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Start notification server in a daemonized thread\n", + " httpd = start_notification_server()\n", + "\n", + " # Setup the MEC application\n", + " (sandbox_name, app_inst_id, sub_id) = mec_app_setup()\n", + "\n", + " # Create subscription\n", + " result, status, headers = subscribe_for_user_events(sandbox_name)\n", + " logger.info('UE location information: status: %s', str(status))\n", + " if status != 200:\n", + " logger.error('Failed to get UE location information')\n", + " else:\n", + " logger.info('UE location information: ' + str(result.data))\n", + " \n", + " # Getting UE location lookup\n", + " result, status = get_ue_location(sandbox_name, '10.100.0.1')\n", + " logger.info('UE location information: status: ' + str(status))\n", + " if status != 200:\n", + " logger.error('Failed to get UE location information')\n", + " else:\n", + " logger.info('UE location information: ' + str(result.data))\n", + "\n", + " # Wait for the notification\n", + " counter = 0\n", + " while not got_notification and counter < 30:\n", + " logger.info('Waiting for subscription...')\n", + " time.sleep(STABLE_TIME_OUT)\n", + " counter += 1\n", + " # End of 'while' statement\n", + "\n", + " # Stop notification server\n", + " stop_notification_server(httpd)\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create our third MEC application: how to use V2X MEC Services\n", + "\n", + "After doing the logging, network scenario activation, MEC application instance creation steps, we are ready to exploit the MEC services exposed by the MEC Sandbox.\n", + "\n", + "In this clause, we use the following functionalities provided by MEC-030:\n", + "- Getting UU unicast provisioning information (ETSI GS MEC 030 Clause 5.5.1)\n", + "- Subscribe to the V2X message distribution server (ETSI GS MEC 030 Clause 5.5.7)\n", + "- Delete subscription\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Getting UU unicast provisioning information\n", + "\n", + "The purpose is to query provisioning information for V2X communication over Uu unicast." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def send_uu_unicast_provisioning_info(sandbox_name: str, ecgi: str) -> object:\n", + " \"\"\"\n", + " Request for V2X communication over Uu unicast information\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param ecgi: Comma separated list of locations to identify a cell of a base station or a particular geographical area\n", + " :return The Uu unicast provisioning information on success, None otherwise\n", + " :see ETSI GS MEC 030 V3.2.1 (2024-02) Clause 5.5.1 Sending a request for provisioning information for V2X communication over Uu unicast\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> send_uu_unicast_provisioning_info: ' + ecgi)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/vis/v2/queries/uu_unicast_provisioning_info'\n", + " logger.debug('send_uu_unicast_provisioning_info: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " query_params = []\n", + " query_params.append(('location_info', 'ecgi,' + ecgi))\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " (result, status, header) = service_api.call_api(url, 'GET', header_params=header_params, path_params=path_params, query_params=query_params, async_req=False)\n", + " return (result, status, header)\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status, None)\n", + " # End of function send_uu_unicast_provisioning_info" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's create the our second MEC application.\n", + "The sequence is the following:\n", + "- Mec application setup\n", + "- Get UU unicast provisioning information\n", + "- Mec application termination\n", + "\n", + "Note that the UU unicast provisioning information is returned as a JSON string. To de-serialized it into a Python data structure, please refer to clause [Subscribing to V2X message distribution server](#subscribing_to_v2x_message_distribution_server)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Putting everything together" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the second sprint of our skeleton of our MEC application:\n", + " - Mec application setup\n", + " - Get UU unicast provisioning information\n", + " - Mec application termination\n", + " \"\"\" \n", + " global logger, nw_scenarios\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Setup the MEC application\n", + " (sandbox_name, app_inst_id, sub_id) = mec_app_setup()\n", + "\n", + " # Get UU unicast provisioning information\n", + " ecgi = \"268708941961,268711972264\" # List of ecgi spearated by a ','\n", + " result, status, header = send_uu_unicast_provisioning_info(sandbox_name, ecgi)\n", + " logger.info('UU unicast provisioning information: status: %s', str(status))\n", + " if status != 200:\n", + " logger.error('Failed to get UU unicast provisioning information')\n", + " else:\n", + " logger.info('UU unicast provisioning information: %s', str(result.data))\n", + "\n", + " # Any processing comes here\n", + " logger.info('body: ' + str(result.data))\n", + " data = json.loads(result.data)\n", + " logger.info('data: ' + str(data))\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Subscribing to V2X message distribution server\n", + "\n", + "Here, we need to come back to the MEC 030 standard to create the type V2xMsgSubscription. It involves the creation of a set of basic types described below.\n", + "\n", + "These new type shall be 'JSON' serializable. It means that they have to implement the following methods:\n", + "\n", + "- to_dict()\n", + "- to_str()\n", + "- \\_\\_repr\\_\\_()\n", + "- \\_\\_eq\\_\\_()\n", + "- \\_\\_ne\\_\\_()\n", + "\n", + "**Reference:** ETSI GS MEC 030 V3.2.1 (2024-02) Clause 6.5.13 Type: LinkType\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class LinkType(object):\n", + " swagger_types = {'href': 'str'}\n", + " attribute_map = {'href': 'href'}\n", + " def __init__(self, href=None): # noqa: E501\n", + " self._href = None\n", + " if href is not None:\n", + " self._href = href\n", + " @property\n", + " def href(self):\n", + " return self._href\n", + " @href.setter\n", + " def href(self, href):\n", + " self._href = href\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(LinkType, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, LinkType):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class Links(object):\n", + " swagger_types = {'self': 'LinkType'}\n", + " attribute_map = {'self': 'self'}\n", + " def __init__(self, self_=None): # noqa: E501\n", + " self._self = None\n", + " if self_ is not None:\n", + " self._self = self_\n", + " @property\n", + " def self_(self):\n", + " return self._self\n", + " @self_.setter\n", + " def self_(self, self_):\n", + " self._self = self_\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(Links, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Links):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class TimeStamp(object):\n", + " swagger_types = {'seconds': 'int', 'nano_seconds': 'int'}\n", + " attribute_map = {'seconds': 'seconds', 'nano_seconds': 'nanoSeconds'}\n", + " def __init__(self, seconds=None, nano_seconds=None): # noqa: E501\n", + " self._seconds = None\n", + " self._nano_seconds = None\n", + " if seconds is not None:\n", + " self._seconds = seconds\n", + " if nano_seconds is not None:\n", + " self._nano_seconds = nano_seconds\n", + " @property\n", + " def seconds(self):\n", + " return self._seconds\n", + " @seconds.setter\n", + " def seconds(self, seconds):\n", + " self._seconds = seconds\n", + " @property\n", + " def nano_seconds(self):\n", + " return self._nano_seconds\n", + " @nano_seconds.setter\n", + " def nano_seconds(self, nano_seconds):\n", + " self._nano_seconds = nano_seconds\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(TimeStamp, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, TimeStamp):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The cell below implements the V2xMsgSubscription data structure.\"}\n", + "Reference: ETSI GS MEC 030 V3.2.1 (2024-02) Clause 6.3.5 Type: V2xMsgSubscription\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class V2xMsgSubscription(object):\n", + " swagger_types = {'links': 'Links', 'callback_reference': 'str', 'filter_criteria': 'V2xMsgSubscriptionFilterCriteria', 'request_test_notification': 'bool', 'subscription_type': 'str'}\n", + " attribute_map = {'links': 'Links', 'callback_reference': 'callbackReference', 'filter_criteria': 'filterCriteria', 'request_test_notification': 'requestTestNotification', 'subscription_type': 'subscriptionType'}\n", + " def __init__(self, links=None, callback_reference=None, filter_criteria=None, request_test_notification=None): # noqa: E501\n", + " self._links = None\n", + " self._callback_reference = None\n", + " self._filter_criteria = None\n", + " self._request_test_notification = None\n", + " self._subscription_type = \"V2xMsgSubscription\"\n", + " if links is not None:\n", + " self.links = links\n", + " if callback_reference is not None:\n", + " self.callback_reference = callback_reference\n", + " if filter_criteria is not None:\n", + " self.filter_criteria = filter_criteria\n", + " if request_test_notification is not None:\n", + " self.request_test_notification = request_test_notification\n", + " @property\n", + " def links(self):\n", + " return self._links\n", + " @links.setter\n", + " def links(self, links):\n", + " self_.links = links\n", + " @property\n", + " def callback_reference(self):\n", + " return self._callback_reference\n", + " @callback_reference.setter\n", + " def callback_reference(self, callback_reference):\n", + " self._callback_reference = callback_reference\n", + " @property\n", + " def links(self):\n", + " return self._links\n", + " @links.setter\n", + " def links(self, links):\n", + " self._links = links\n", + " @property\n", + " def filter_criteria(self):\n", + " return self._filter_criteria\n", + " @filter_criteria.setter\n", + " def filter_criteria(self, filter_criteria):\n", + " self._filter_criteria = filter_criteria\n", + " @property\n", + " def request_test_notification(self):\n", + " return self._request_test_notification\n", + " @request_test_notification.setter\n", + " def request_test_notification(self, request_test_notification):\n", + " self._request_test_notification = request_test_notification\n", + " @property\n", + " def subscription_type(self):\n", + " return self._subscription_type\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(V2xMsgSubscription, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, V2xMsgSubscription):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class V2xMsgSubscriptionFilterCriteria(object):\n", + " swagger_types = {'msg_type': 'list[str]', 'std_organization': 'str'}\n", + " attribute_map = {'msg_type': 'MsgType', 'std_organization': 'stdOrganization'}\n", + " def __init__(self, msg_type, std_organization): # noqa: E501\n", + " self._msg_type = None\n", + " self._std_organization = None\n", + " self.msg_type = msg_type\n", + " self.std_organization = std_organization\n", + " @property\n", + " def msg_type(self):\n", + " return self._msg_type\n", + " @msg_type.setter\n", + " def msg_type(self, msg_type):\n", + " self._msg_type = msg_type\n", + " @property\n", + " def std_organization(self):\n", + " return self._std_organization\n", + " @std_organization.setter\n", + " def std_organization(self, std_organization):\n", + " self._std_organization = std_organization\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(V2xMsgSubscriptionFilterCriteria, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, V2xMsgSubscriptionFilterCriteria):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the V2X message subscription function. The HTTP Request message body contains a 'JSON' serialized instance of the class V2xMsgSubscription.\n", + "\n", + "Reference: ETSI GS MEC 030 V3.2.1 (2024-02) Clause 5.5.10 V2X message interoperability\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def subscribe_v2x_message(sandbox_name: str, v2xMsgSubscription: V2xMsgSubscription) -> object:\n", + " \"\"\"\n", + " Request to subscribe the V2X messages which come from different vehicle OEMs or operators\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :param sub_id: The subscription identifier\n", + " :return The HTTP response, the HTTP response status, the subscription identifier and the subscription URL on success, None otherwise\n", + " :see ETSI GS MEC 030 V3.2.1 (2024-02) Clause 5.5.10 V2X message interoperability\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> subscribe_v2x_message: v2xMsgSubscription: ' + str(v2xMsgSubscription))\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/vis/v2/subscriptions'\n", + " logger.debug('subscribe_v2x_message: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " (result, status, headers) = service_api.call_api(url, 'POST', header_params=header_params, path_params=path_params, body=v2xMsgSubscription, async_req=False)\n", + " return (result, status, extract_sub_id(headers['Location']), headers['Location'])\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status, None)\n", + " # End of function subscribe_v2x_message" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a generic function to delete any MEC service subscription based on the subscription resource URL provided in the Location header of the subscription creation response." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def delete_mec_subscription(resource_url: str) -> int:\n", + " \"\"\"\n", + " Delete any existing MEC subscription\n", + " :param resource_url: The subscription URL\n", + " :return 0 on success, -1 otherwise\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> delete_mec_subscription: resource_url: ' + resource_url)\n", + " try:\n", + " res = urllib3.util.parse_url(resource_url)\n", + " if res is None:\n", + " logger.error('delete_mec_subscription: Failed to paerse URL')\n", + " return -1\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " service_api.call_api(res.path, 'DELETE', header_params=header_params, async_req=False)\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return -1\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finaly, here is how to implement the V2X message subscription:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the second sprint of our skeleton of our MEC application:\n", + " - Mec application setup\n", + " - Subscribe to V2XMessage\n", + " - Delete subscription\n", + " - Mec application termination\n", + " \"\"\" \n", + " global MEC_PLTF, CALLBACK_URI, logger\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Setup the MEC application\n", + " (sandbox_name, app_inst_id, sub_id) = mec_app_setup()\n", + "\n", + " # Create a V2X message subscritpion\n", + " filter_criteria = V2xMsgSubscriptionFilterCriteria(['1', '2'], 'ETSI')\n", + " v2xMsgSubscription = V2xMsgSubscription(callback_reference = CALLBACK_URI + '/vis/v2/v2x_msg_notification', filter_criteria = filter_criteria)\n", + " result, status, v2x_sub_id, v2x_resource = subscribe_v2x_message(sandbox_name, v2xMsgSubscription)\n", + " if status != 201:\n", + " logger.error('Failed to create subscription')\n", + "\n", + " # Any processing here\n", + " logger.info('body: ' + str(result.data))\n", + " data = json.loads(result.data)\n", + " logger.info('data: %s', str(data))\n", + " logger.info('app_inst_id: ' + app_inst_id.id)\n", + " if sub_id is not None:\n", + " logger.info('sub_id: ' + sub_id)\n", + " time.sleep(STABLE_TIME_OUT)\n", + "\n", + " # Delete the V2X message subscritpion\n", + " delete_mec_subscription(v2x_resource)\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Putting everything together\n", + "\n", + "let's add a subscription the our previous MEC application.\n", + "The sequence is the following:\n", + "- Mec application setup\n", + "- Start the notification server\n", + "- Get UU unicast provisioning information\n", + "- Add subscription\n", + "- Stop the notification server\n", + "- Mec application termination" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the third sprint of our skeleton of our MEC application:\n", + " - Mec application setup\n", + " - Start the notification server\n", + " - Get UU unicast provisioning information\n", + " - Add subscription\n", + " - Stop the notification server\n", + " - Mec application termination\n", + " \"\"\" \n", + " global CALLBACK_URI, logger\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Setup the MEC application\n", + " (sandbox_name, app_inst_id, sub_id) = mec_app_setup()\n", + "\n", + " # Get UU unicast provisioning information\n", + " ecgi = \"268708941961,268711972264\" # List of ecgi spearated by a ','\n", + " result = send_uu_unicast_provisioning_info(sandbox_name, ecgi)\n", + " if result is None:\n", + " logger.error('Failed to get UU unicast provisioning information')\n", + " else:\n", + " logger.info('UU unicast provisioning information: ' + str(result))\n", + "\n", + " # Start notification server in a daemonized thread\n", + " httpd = start_notification_server()\n", + "\n", + " # Create a V2X message subscritpion\n", + " filter_criteria = V2xMsgSubscriptionFilterCriteria(['1', '2'], 'ETSI')\n", + " v2xMsgSubscription = V2xMsgSubscription(callback_reference = CALLBACK_URI + '/vis/v2/v2x_msg_notification', filter_criteria = filter_criteria)\n", + " result, status, v2x_sub_id, v2x_resource = subscribe_v2x_message(sandbox_name, v2xMsgSubscription)\n", + " if status != 201:\n", + " logger.error('Failed to create subscription')\n", + "\n", + " # Any processing here\n", + " logger.info('body: ' + str(result.data))\n", + " data = json.loads(result.data)\n", + " logger.info('data: %s', str(data))\n", + " logger.info('v2x_resource: ' + v2x_resource)\n", + " if sub_id is not None:\n", + " logger.info('sub_id: ' + sub_id)\n", + " time.sleep(STABLE_TIME_OUT)\n", + "\n", + " # Stop notification server\n", + " stop_notification_server(httpd)\n", + "\n", + " # Delete the V2X message subscritpion\n", + " delete_mec_subscription(v2x_resource)\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create our fourth MEC application: how to use V2X QoS Prediction\n", + "\n", + "The MEC Sanbox V2X QoS Prediction is based on a grid Map of Monaco City where areas are categorized into residential, commercial and coastal. \n", + "PoAs (Point Of Access) are categorized depending on where they lie in each grid. \n", + "Each category has its own traffic load patterns which are pre-determin. The V2X QoS Prediction) will give more accurate values of RSRP and RSRQ based on the diurnal traffic patterns for each. The network scenario named \"4g-5g-v2x-macro\" must be used to get access to the V2X QoS Prediction feature.\n", + "\n", + "**Note:** The MEC Sanbox V2X QoS Prediction is enabled when the PredictedQos.routes.routeInfo.time attribute is present in the request (see ETSI GS MEC 030 V3.2.1 (2024-02) Clause 6.2.6 Type: Preditecd QoS)\n", + "\n", + "Limitations:\n", + "* The Location Granularity is currently not being validated as RSRP/RSRP calculations are done at the exact location provided by the user.\n", + "* Time Granularity is currently not supported by the Prediction Function (design limitations of the minimal, emulated, pre-determined traffic prediction)\n", + "* Upper limit on the number of elements (10 each) in the routes and routeInfo structures (arrays) to not affect user experience and respoy\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The table below describes the excepted Qos with and without the prediction model in deiffrent area and at different time.\n", + "\n", + "| Location | Time | PoA | Category | Status | QoS without Prediction Model | QoS with Prediction Model | Expected |\n", + "| \t | (Unix time in sec) | Standard (GMT) | | | | RSRP | RSRQ | RSRP | RSRQ | |\n", + "| ------------------- | ----------- | -------------- | ---------------- | ----------- | ------------- | -------------- | ----------- | ----------- | ----------- | -------- |\n", + "| 43.729416,7.414853 | 1653295620 | 08:47:00 | 4g-macro-cell-2 | Residential | Congested | 63 | 21 | 60 | 20 | Yes |\n", + "| 43.732456,7.418417 | 1653299220 | 09:47:00 | 4g-macro-cell-3 | Residential | Not Congested | 55 | 13 | 55 | 13 | Yes |\n", + "| 43.73692,7.4209256 | 1653302820 | 10:47:00 | 4g-macro-cell-6 | Coastal | Not Congested | 68 | 26 | 68 | 26 | Yes |\n", + "| 43.738007,7.4230533 | 1653305220 | 11:27:00 | 4g-macro-cell-6 | Coastal | Not Congested | 55 | 13 | 55 | 13 | Yes |\n", + "| 43.739685,7.424881 | 1653308820 | 12:27:00 | 4g-macro-cell-7 | Commercial | Congested | 63 | 21 | 40 | 13 | Yes |\n", + "| 43.74103,7.425759 | 1653312600 | 13:30:00 | 4g-macro-cell-7 | Commercial | Congested | 56 | 14 | 40 | 8 | Yes |\n", + "| 43.74258,7.4277945 | 1653315900 | 14:25:00 | 4g-macro-cell-8 | Coastal | Congested | 59 | 17 | 47 | 13 | Yes |\n", + "| 43.744972,7.4295254 | 1653318900 | 15:15:00 | 4g-macro-cell-8 | Coastal | Congested | 53 | 11 | 40 | 5 | Yes |\n", + "| 43.74773,7.4320855 | 1653322500 | 16:15:00 | 5g-small-cell-14 | Commercial | Congested | 78 | 69 | 60 | 53 | Yes |\n", + "| 43.749264,7.435894 | 1653329700 | 18:15:00 | 5g-small-cell-20 | Commercial | Not Congested | 84 | 72 | 84 | 72 | Yes |\t72\t84\t72\tYes\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The image below illustrate the table above: [here](images/V2X Predicted QoS.jpg).\n", + "\n", + "Here is an example of a basic V2X predicted QoS request based on two point in path at 8am in Residential area:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```json\n", + "{\n", + " \"predictionTarget\": \"SINGLE_UE_PREDICTION\",\n", + " \"timeGranularity\": null,\n", + " \"locationGranularity\": \"30\",\n", + " \"routes\": [\n", + " {\n", + " \"routeInfo\": [\n", + " {\n", + " \"location\": {\n", + " \"geoArea\": {\n", + " \"latitude\": 43.729416,\n", + " \"longitude\": 7.414853\n", + " }\n", + " },\n", + " \"time\": {\n", + " \"nanoSeconds\": 0,\n", + " \"seconds\": 1653295620\n", + " }\n", + " },\n", + " {\n", + " \"location\": {\n", + " \"geoArea\": {\n", + " \"latitude\": 43.732456,\n", + " \"longitude\": 7.418417\n", + " }\n", + " },\n", + " \"time\": {\n", + " \"nanoSeconds\": 0,\n", + " \"seconds\": 1653299220\n", + " ]\n", + " }\n", + " ]\n", + "}\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let first create the required types before to prepare a V2X Predicted QoS request based on the JSON above.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Routes(object):\n", + " swagger_types = {'_route_info': 'list[RouteInfo]'}\n", + " attribute_map = {'_route_info': 'routeInfo'}\n", + " def __init__(self, route_info:list): # noqa: E501\n", + " self._route_info = None\n", + " self.route_info = route_info\n", + " @property\n", + " def route_info(self):\n", + " return self._route_info\n", + " @route_info.setter\n", + " def route_info(self, route_info):\n", + " if route_info is None:\n", + " raise ValueError(\"Invalid value for `route_info`, must not be `None`\") # noqa: E501\n", + " self._route_info = route_info\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(Routes, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Routes):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class LocationInfo(object):\n", + " swagger_types = {'_ecgi': 'Ecgi', '_geo_area': 'LocationInfoGeoArea'}\n", + " attribute_map = {'_ecgi': 'ecgi', '_geo_area': 'geoArea'}\n", + " def __init__(self, ecgi=None, geo_area=None): # noqa: E501\n", + " self._ecgi = None\n", + " self._geo_area = None\n", + " self.discriminator = None\n", + " if ecgi is not None:\n", + " self.ecgi = ecgi\n", + " if geo_area is not None:\n", + " self.geo_area = geo_area\n", + " @property\n", + " def ecgi(self):\n", + " return self._ecgi\n", + " @ecgi.setter\n", + " def ecgi(self, ecgi):\n", + " self._ecgi = ecgi\n", + " @property\n", + " def geo_area(self):\n", + " return self._geo_area\n", + " @geo_area.setter\n", + " def geo_area(self, geo_area):\n", + " self._geo_area = geo_area\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(LocationInfo, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, LocationInfo):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class RouteInfo(object):\n", + " swagger_types = {'_location': 'LocationInfo', '_time_stamp': 'TimeStamp'}\n", + " attribute_map = {'_location': 'location', '_time_stamp': 'time'}\n", + " def __init__(self, location:LocationInfo, time_stamp=None): # noqa: E501\n", + " self._location = None\n", + " self.location = location\n", + " self._time_stamp = None\n", + " if time_stamp is not None:\n", + " self.time_stamp = time_stamp\n", + " @property\n", + " def location(self):\n", + " return self._location\n", + " @location.setter\n", + " def location(self, location):\n", + " if location is None:\n", + " raise ValueError(\"Invalid value for `location`, must not be `None`\") # noqa: E501\n", + " self._location = location\n", + " @property\n", + " def time_stamp(self):\n", + " return self._time_stamp\n", + " @time_stamp.setter\n", + " def time_stamp(self, time_stamp):\n", + " self._time_stamp = time_stamp\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(RouteInfo, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, RouteInfo):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class LocationInfoGeoArea(object):\n", + " swagger_types = {'_latitude': 'float', '_longitude': 'float'}\n", + " attribute_map = {'_latitude': 'latitude', '_longitude': 'longitude'}\n", + " def __init__(self, latitude, longitude): # noqa: E501\n", + " self._latitude = None\n", + " self._longitude = None\n", + " self.discriminator = None\n", + " if latitude is not None:\n", + " self.latitude = latitude\n", + " if longitude is not None:\n", + " self.longitude = longitude\n", + " @property\n", + " def latitude(self):\n", + " return self._latitude\n", + " @latitude.setter\n", + " def latitude(self, latitude):\n", + " if latitude is None:\n", + " raise ValueError(\"Invalid value for `latitude`, must not be `None`\") # noqa: E501\n", + " self._latitude = latitude\n", + " @property\n", + " def longitude(self):\n", + " return self._longitude\n", + " @longitude.setter\n", + " def longitude(self, longitude):\n", + " if longitude is None:\n", + " raise ValueError(\"Invalid value for `longitude`, must not be `None`\") # noqa: E501\n", + " self._longitude = longitude\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(LocationInfoGeoArea, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, LocationInfoGeoArea):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class Ecgi(object):\n", + " swagger_types = {'_cellId': 'CellId', '_plmn': 'Plmn'}\n", + " attribute_map = {'_cellId': 'cellId', '_plmn': 'plmn'}\n", + " def __init__(self, cellId=None, plmn=None): # noqa: E501\n", + " self._cellId = None\n", + " self._plmn = None\n", + " self.discriminator = None\n", + " if cellId is not None:\n", + " self.cellId = cellId\n", + " if plmn is not None:\n", + " self.plmn = plmn\n", + " @property\n", + " def cellId(self):\n", + " return self._cellId\n", + " @cellId.setter\n", + " def cellId(self, cellId):\n", + " self._cellId = cellId\n", + " @property\n", + " def plmn(self):\n", + " return self._plmn\n", + " @plmn.setter\n", + " def plmn(self, plmn):\n", + " self._plmn = plmn\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(Ecgi, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Ecgi):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class CellId(object):\n", + " swagger_types = {'_cellId': 'str'}\n", + " attribute_map = {'_cellId': 'cellId'}\n", + " def __init__(self, cellId): # noqa: E501\n", + " self._cellId = None\n", + " self.cellId = cellId\n", + " @property\n", + " def cellId(self):\n", + " return self._cellId\n", + " @cellId.setter\n", + " def cellId(self, cellId):\n", + " if cellId is None:\n", + " raise ValueError(\"Invalid value for `cellId`, must not be `None`\") # noqa: E501\n", + " self._cellId = cellId\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(CellId, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, CellId):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class Plmn(object):\n", + " swagger_types = {'_mcc': 'str', '_mnc': 'str'}\n", + " attribute_map = {'_mcc': 'mcc', '_mnc': 'mnc'}\n", + " def __init__(self, mcc:str, mnc:str): # noqa: E501\n", + " self.discriminator = None\n", + " self._mcc = None\n", + " self._mnc = None\n", + " self.mcc = mcc\n", + " self.mnc = mnc\n", + " @property\n", + " def mcc(self):\n", + " return self._mcc\n", + " @mcc.setter\n", + " def kpi_nmccame(self, mcc):\n", + " if mcc is None:\n", + " raise ValueError(\"Invalid value for `mcc`, must not be `None`\") # noqa: E501\n", + " self._mcc = mcc\n", + " @property\n", + " def mnc(self):\n", + " return self._mnc\n", + " @mnc.setter\n", + " def kpi_nmccame(self, mnc):\n", + " if mnc is None:\n", + " raise ValueError(\"Invalid value for `mnc`, must not be `None`\") # noqa: E501\n", + " self._mnc = mnc\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(Plmn, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Plmn):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class QosKpi(object):\n", + " swagger_types = {'_kpi_name': 'str', '_kpi_value': 'str', '_confidence': 'str'}\n", + " attribute_map = {'_kpi_name': 'kpiName', '_kpi_value': 'kpiValue', '_confidence': 'Confidence'}\n", + " def __init__(self, kpi_name:str, kpi_value:str, confidence=None): # noqa: E501\n", + " self._kpi_name = None\n", + " self._kpi_value = None\n", + " self._confidence = None\n", + " self.kpi_name = kpi_name\n", + " self.kpi_value = kpi_value\n", + " if confidence is not None:\n", + " self.confidences = confidence\n", + " @property\n", + " def kpi_name(self):\n", + " return self._kpi_name\n", + " @kpi_name.setter\n", + " def kpi_name(self, kpi_name):\n", + " if kpi_name is None:\n", + " raise ValueError(\"Invalid value for `kpi_name`, must not be `None`\") # noqa: E501\n", + " self._kpi_name = kpi_name\n", + " @property\n", + " def kpi_value(self):\n", + " return self._kpi_value\n", + " @kpi_value.setter\n", + " def kpi_value(self, kpi_value):\n", + " if kpi_value is None:\n", + " raise ValueError(\"Invalid value for `kpi_value`, must not be `None`\") # noqa: E501\n", + " self._kpi_value = kpi_value\n", + " @property\n", + " def confidence(self):\n", + " return self._confidence\n", + " @confidence.setter\n", + " def confidence(self, confidence):\n", + " self._confidence = confidence\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(QosKpi, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, QosKpi):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class Stream(object):\n", + " swagger_types = {'_stream_id': 'str', '_qos_kpi': 'list[QosKpi]'}\n", + " attribute_map = {'_stream_id': 'streamId', '_qos_kpi': 'qosKpi'}\n", + " def __init__(self, stream_id:str, qos_kpi:list): # noqa: E501\n", + " self._stream_id = None\n", + " self._qos_kpi = None\n", + " self.stream_id = stream_id\n", + " self.qos_kpi = qos_kpi\n", + " @property\n", + " def stream_id(self):\n", + " return self._stream_id\n", + " @stream_id.setter\n", + " def stream_id(self, stream_id):\n", + " if stream_id is None:\n", + " raise ValueError(\"Invalid value for `stream_id`, must not be `None`\") # noqa: E501\n", + " self._stream_id = stream_id\n", + " @property\n", + " def qos_kpi(self):\n", + " return self._qos_kpi\n", + " @qos_kpi.setter\n", + " def qos_kpi(self, qos_kpi):\n", + " if qos_kpi is None:\n", + " raise ValueError(\"Invalid value for `qos_kpi`, must not be `None`\") # noqa: E501\n", + " self._qos_kpi = qos_kpi\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(Stream, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Stream):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class Qos(object):\n", + " swagger_types = {'_stream': 'list[Stream]'}\n", + " attribute_map = {'_stream': 'stream'}\n", + " def __init__(self, stream:list): # noqa: E501\n", + " self._stream = None\n", + " self.stream = stream\n", + " @property\n", + " def stream(self):\n", + " return self._stream\n", + " @stream.setter\n", + " def stream(self, stream):\n", + " if stream is None:\n", + " raise ValueError(\"Invalid value for `stream`, must not be `None`\") # noqa: E501\n", + " self._stream = stream\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(Qos, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Qos):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class PredictedQos(object):\n", + " swagger_types = {'_location_granularity': 'str', '_notice_period': 'TimeStamp', '_prediction_area': 'PredictionArea', '_prediction_target': 'str', '_qos': 'Qos', '_routes': 'list[Routes]', '_time_granularity': 'TimeStamp'}\n", + " attribute_map = {'_location_granularity': 'locationGranularity', '_notice_period': 'noticePeriod', '_prediction_area': 'predictionArea', '_prediction_target': 'predictionTarget', '_qos': 'qos', '_routes': 'routes', '_time_granularity': 'timeGranularity'}\n", + " def __init__(self, prediction_target:str, location_granularity:str, notice_period=None, time_granularity=None, prediction_area=None, routes=None, qos=None): # noqa: E501\n", + " self._prediction_target = None\n", + " self._time_granularity = None\n", + " self._location_granularity = None\n", + " self._notice_period = None\n", + " self._prediction_area = None\n", + " self._routes = None\n", + " self._qos = None\n", + " self._prediction_target = prediction_target\n", + " if time_granularity is not None:\n", + " self.time_granularity = time_granularity\n", + " self.location_granularity = location_granularity\n", + " if notice_period is not None:\n", + " self.notice_period = notice_period\n", + " if prediction_area is not None:\n", + " self.prediction_area = prediction_area\n", + " if routes is not None:\n", + " self.routes = routes\n", + " if qos is not None:\n", + " self.qos = qos\n", + " @property\n", + " def prediction_target(self):\n", + " return self._prediction_target\n", + " @prediction_target.setter\n", + " def prediction_target(self, prediction_target):\n", + " if prediction_target is None:\n", + " raise ValueError(\"Invalid value for `prediction_target`, must not be `None`\") # noqa: E501\n", + " self._prediction_target = prediction_target\n", + " @property\n", + " def time_granularity(self):\n", + " return self._time_granularity\n", + " @time_granularity.setter\n", + " def time_granularity(self, time_granularity):\n", + " self._time_granularity = time_granularity\n", + " @property\n", + " def location_granularity(self):\n", + " return self._location_granularity\n", + " @location_granularity.setter\n", + " def location_granularity(self, location_granularity):\n", + " if location_granularity is None:\n", + " raise ValueError(\"Invalid value for `location_granularity`, must not be `None`\") # noqa: E501\n", + " self._location_granularity = location_granularity\n", + " @property\n", + " def notice_period(self):\n", + " return self._notice_period\n", + " @notice_period.setter\n", + " def notice_period(self, notice_period):\n", + " self._notice_period = notice_period\n", + " @property\n", + " def prediction_area(self):\n", + " return self._prediction_area\n", + " @prediction_area.setter\n", + " def prediction_area(self, prediction_area):\n", + " self._prediction_area = prediction_area\n", + " @property\n", + " def routes(self):\n", + " return self._routes\n", + " @routes.setter\n", + " def routes(self, routes):\n", + " self._routes = routes\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(PredictedQos, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, PredictedQos):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the V2X Prediscted QoS function.\n", + "\n", + "Reference: ETSI GS MEC 030 V3.2.1 (2024-02) Clause 5.5.5 Sending a request for journey-specific QoS predictions\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_qos_prediction(sandbox_name: str) -> object:\n", + " \"\"\"\n", + " Request to predictede QoS\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return The HTTP response, the HTTP response status and the HTTP response headers on success, None otherwise\n", + " :see ETSI GS MEC 030 V3.2.1 (2024-02) Clause 5.5.5 Sending a request for journey-specific QoS predictions\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> get_qos_prediction: sandbox_name: ' + sandbox_name)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/vis/v2/provide_predicted_qos'\n", + " logger.debug('send_uu_unicast_provisioning_info: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " # HTTP header `Accept`\n", + " header_params = {}\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " # Body request\n", + " loc1 = LocationInfo(geo_area=LocationInfoGeoArea(latitude=43.729416, longitude=7.414853))\n", + " loc2 = LocationInfo(geo_area=LocationInfoGeoArea(latitude=43.732456, longitude=7.418417))\n", + " routeInfo1 = RouteInfo(loc1, TimeStamp(nano_seconds=0, seconds=1653295620))\n", + " routeInfo2 = RouteInfo(loc2, TimeStamp(nano_seconds=0, seconds=1653299220))\n", + " routesInfo = [routeInfo1, routeInfo2]\n", + " predictedQos = PredictedQos(prediction_target=\"SINGLE_UE_PREDICTION\", location_granularity=\"30\", routes=[Routes(routesInfo)])\n", + " (result, status, headers) = service_api.call_api(url, 'POST', header_params=header_params, path_params=path_params, body=predictedQos, async_req=False)\n", + " return (result, status, headers)\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status, None)\n", + " # End of function send_uu_unicast_provisioning_info" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Grouping all together provides the process_main funtion.. The sequence is the following:\n", + "- Mec application setup\n", + "- V2X QoS request\n", + "- Mec application termination\n", + "\n", + "The expected response should be:\n", + "- RSRP: 55\n", + "- RSRQ: 13" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the fourth sprint of our skeleton of our MEC application:\n", + " - Mec application setup\n", + " - V2X QoS request\n", + " - Mec application termination\n", + " \"\"\" \n", + " global logger\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Setup the MEC application\n", + " sandbox_name, app_inst_id, sub_id = mec_app_setup()\n", + "\n", + " # QoS Prediction\n", + " (result, status, headers) = get_qos_prediction(sandbox_name)\n", + " if status != 200:\n", + " logger.error('Failed to get UU unicast provisioning information')\n", + " else:\n", + " logger.info('UU unicast provisioning information: result: %s', str(result.data))\n", + " \n", + " # Any processing here\n", + " logger.info('body: ' + str(result.data))\n", + " data = json.loads(result.data)\n", + " logger.info('data: %s', str(data))\n", + " time.sleep(STABLE_TIME_OUT)\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Our fith MEC application: how to create a new MEC Services\n", + "\n", + "The purpose of this MEC Service application is to provide a custom MEC service that can be use by other MEC applications. For the purpose of this tutorial, our MEC service is simulating some complex calculation based on a set of data provided by the MEC use. \n", + "We will use a second MEC application to exploit the features of our new MEC services.\n", + "\n", + "In this clause, we use the following functionalities provided by MEC-011:\n", + "- Register a new service\n", + "- Retrieve the list of the MEC services exposed by the MEC platform\n", + "- Check that our new MEC service is present in the list of the MEC platform services\n", + "- Execute a request to the MEC service\n", + "- Delete the newly created service\n", + "\n", + "**Note:** We will use a second MEC application to exploit the features of our new MEC services.\n", + "\n", + "**Reference:** ETSI GS MEC 011 V3.2.1 (2024-04) Clause 5.2.4 Service availability update and new service registration\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Bases of the creation of a MEC service\n", + "\n", + "#### Introduction\n", + "\n", + "From the user perspective, a MEC service provides a set of endpoints which describe the interface of the MEC service (see [HTTP REST APIs \n", + "concepts](https://blog.postman.com/rest-api-examples/)). These endpoints come usually with a set of data structures used by the one or more endpoints.\n", + "\n", + "Our service is really basic: it provide one endpoint:\n", + "- GET /statistic/v1/quantity: it computes statistical quantities of a set of data (such as average, max, min, standard deviation)\n", + "\n", + "The body of this GET method is a list of datas:\n", + "```json\n", + "{\"time\":20180124,\"data1\":\"[1516752000,11590.6,11616.9,11590.4,11616.9,0.25202387,1516752060,11622.4,11651.7,11622.4,11644.6,1.03977764]\"}\n", + "```\n", + "\n", + "The response body is the list of statistical quantities:\n", + "```json\n", + "{\"time\":20180124,\"avg\": 0.0,\"max\": 0.0,\"min\": 0.0,\"stddev\": 0.0 }\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MEC mechanisms to create a new service\n", + "\n", + "As described in ETSI GS MEC 011 Clause 5.2.4 Service availability update and new service registration, to create a new MEC service, the following information is required:\n", + "- A MEC Aplication instance: this is the MEC application providing the new MEC service (ETSI GS MEC 011 V3.2.1 Clause 8.2.6.3.4 POST)\n", + "- A ServiceInfo instance which describe the MEC service (ETSI GS MEC 011 V3.2.1 Clause 8.1.2.2 Type: ServiceInfo)\n", + "- As part of the ServiceInfo instance, a TransportInfo (ETSI GS MEC 011 V3.2.1 Clause 8.1.2.3 Type: TransportInfo) instance descibes the endpoints to use the MEC service\n", + "\n", + "When created and available, all the other MEC applications are notified about the existance of this MEC service." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ServiceInfo data type\n", + "\n", + "The cell below describes the ServiceInfo data structure and its dependencies. It will be used to create our MEC servie.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class ServiceInfo(object):\n", + " swagger_types = {'ser_instance_id': 'str','ser_name': 'str','ser_category': 'CategoryRef','version': 'str','state': 'str','transport_id': 'str','transport_info': 'TransportInfo','serializer': 'string','scope_of_locality': 'LocalityType','consumed_local_only': 'bool','is_local': 'bool','liveness_interval': 'int','links': 'ServiceInfoLinks'}\n", + " attribute_map = {'ser_instance_id': 'serInstanceId','ser_name': 'serName','ser_category': 'serCategory','version': 'version','state': 'state','transport_id': 'transportId','transport_info': 'transportInfo','serializer': 'serializer','scope_of_locality': 'scopeOfLocality','consumed_local_only': 'consumedLocalOnly','is_local': 'isLocal','liveness_interval': 'livenessInterval','links': '_links'}\n", + " def __init__(self, ser_instance_id=None, ser_name=None, ser_category=None, version=None, state=None, transport_id=None, transport_info=None, serializer=None, scope_of_locality=None, consumed_local_only=None, is_local=None, liveness_interval=None, links=None): # noqa: E501\n", + " self._ser_instance_id = None\n", + " self._ser_name = None\n", + " self._ser_category = None\n", + " self._version = None\n", + " self._state = None\n", + " self._transport_id = None\n", + " self._transport_info = None\n", + " self._serializer = None\n", + " self._scope_of_locality = None\n", + " self._consumed_local_only = None\n", + " self._is_local = None\n", + " self._liveness_interval = None\n", + " self._links = None\n", + " self.discriminator = None\n", + " if ser_instance_id is not None:\n", + " self.ser_instance_id = ser_instance_id\n", + " self.ser_name = ser_name\n", + " if ser_category is not None:\n", + " self.ser_category = ser_category\n", + " self.version = version\n", + " self.state = state\n", + " if transport_id is not None:\n", + " self.transport_id = transport_id\n", + " self.transport_info = transport_info\n", + " self.serializer = serializer\n", + " if scope_of_locality is not None:\n", + " self.scope_of_locality = scope_of_locality\n", + " if consumed_local_only is not None:\n", + " self.consumed_local_only = consumed_local_only\n", + " if is_local is not None:\n", + " self.is_local = is_local\n", + " if liveness_interval is not None:\n", + " self.liveness_interval = liveness_interval\n", + " if links is not None:\n", + " self.links = links\n", + " @property\n", + " def ser_instance_id(self):\n", + " return self._ser_instance_id\n", + " @ser_instance_id.setter\n", + " def ser_instance_id(self, ser_instance_id):\n", + " self._ser_instance_id = ser_instance_id\n", + " @property\n", + " def ser_name(self):\n", + " return self._ser_name\n", + " @ser_name.setter\n", + " def ser_name(self, ser_name):\n", + " if ser_name is None:\n", + " raise ValueError(\"Invalid value for `ser_name`, must not be `None`\") # noqa: E501\n", + " self._ser_name = ser_name\n", + " @property\n", + " def ser_category(self):\n", + " return self._ser_category\n", + " @ser_category.setter\n", + " def ser_category(self, ser_category):\n", + " self._ser_category = ser_category\n", + " @property\n", + " def version(self):\n", + " return self._version\n", + " @version.setter\n", + " def version(self, version):\n", + " if version is None:\n", + " raise ValueError(\"Invalid value for `version`, must not be `None`\") # noqa: E501\n", + " self._version = version\n", + " @property\n", + " def state(self):\n", + " return self._state\n", + " @state.setter\n", + " def state(self, state):\n", + " if state is None:\n", + " raise ValueError(\"Invalid value for `state`, must not be `None`\") # noqa: E501\n", + " self._state = state\n", + " @property\n", + " def transport_id(self):\n", + " return self._transport_id\n", + " @transport_id.setter\n", + " def transport_id(self, transport_id):\n", + " self._transport_id = transport_id\n", + " @property\n", + " def transport_info(self):\n", + " return self._transport_info\n", + " @transport_info.setter\n", + " def transport_info(self, transport_info):\n", + " if transport_info is None:\n", + " raise ValueError(\"Invalid value for `transport_info`, must not be `None`\") # noqa: E501\n", + " self._transport_info = transport_info\n", + " @property\n", + " def serializer(self):\n", + " return self._serializer\n", + " @serializer.setter\n", + " def serializer(self, serializer):\n", + " if serializer is None:\n", + " raise ValueError(\"Invalid value for `serializer`, must not be `None`\") # noqa: E501\n", + " self._serializer = serializer\n", + " @property\n", + " def scope_of_locality(self):\n", + " return self._scope_of_locality\n", + " @scope_of_locality.setter\n", + " def scope_of_locality(self, scope_of_locality):\n", + " self._scope_of_locality = scope_of_locality\n", + " @property\n", + " def consumed_local_only(self):\n", + " return self._consumed_local_only\n", + " @consumed_local_only.setter\n", + " def consumed_local_only(self, consumed_local_only):\n", + " self._consumed_local_only = consumed_local_only\n", + " @property\n", + " def is_local(self):\n", + " return self._is_local\n", + " @is_local.setter\n", + " def is_local(self, is_local):\n", + " self._is_local = is_local\n", + " @property\n", + " def liveness_interval(self):\n", + " return self._liveness_interval\n", + " @liveness_interval.setter\n", + " def liveness_interval(self, liveness_interval):\n", + " self._liveness_interval = liveness_interval\n", + " @property\n", + " def links(self):\n", + " return self._links\n", + " @links.setter\n", + " def links(self, links):\n", + " self._links = links\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(ServiceInfo, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, ServiceInfo):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class CategoryRef(object):\n", + " swagger_types = {'href': 'str','id': 'str','name': 'str','version': 'str'}\n", + " attribute_map = {'href': 'href','id': 'id','name': 'name','version': 'version'}\n", + " def __init__(self, href=None, id=None, name=None, version=None): # noqa: E501\n", + " self._href = None\n", + " self._id = None\n", + " self._name = None\n", + " self._version = None\n", + " self.discriminator = None\n", + " self.href = href\n", + " self.id = id\n", + " self.name = name\n", + " self.version = version\n", + " @property\n", + " def href(self):\n", + " return self._href\n", + " @href.setter\n", + " def href(self, href):\n", + " if href is None:\n", + " raise ValueError(\"Invalid value for `href`, must not be `None`\") # noqa: E501\n", + " self._href = href\n", + " @property\n", + " def id(self):\n", + " return self._id\n", + " @id.setter\n", + " def id(self, id):\n", + " if id is None:\n", + " raise ValueError(\"Invalid value for `id`, must not be `None`\") # noqa: E501\n", + " self._id = id\n", + " @property\n", + " def name(self):\n", + " return self._name\n", + " @name.setter\n", + " def name(self, name):\n", + " if name is None:\n", + " raise ValueError(\"Invalid value for `name`, must not be `None`\") # noqa: E501\n", + " self._name = name\n", + " @property\n", + " def version(self):\n", + " return self._version\n", + " @version.setter\n", + " def version(self, version):\n", + " if version is None:\n", + " raise ValueError(\"Invalid value for `version`, must not be `None`\") # noqa: E501\n", + " self._version = version\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(CategoryRef, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, CategoryRef):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class TransportInfo(object):\n", + " swagger_types = {\n", + " 'id': 'str','name': 'str','description': 'str','type': 'str','protocol': 'str','version': 'str','endpoint': 'OneOfTransportInfoEndpoint','security': 'SecurityInfo','impl_specific_info': 'str'}\n", + " attribute_map = {'id': 'id','name': 'name','description': 'description','type': 'type','protocol': 'protocol','version': 'version','endpoint': 'endpoint','security': 'security','impl_specific_info': 'implSpecificInfo'}\n", + " def __init__(self, id=None, name=None, description=None, type=None, protocol=None, version=None, endpoint=None, security=None, impl_specific_info=None): # noqa: E501\n", + " self._id = None\n", + " self._name = None\n", + " self._description = None\n", + " self._type = None\n", + " self._protocol = None\n", + " self._version = None\n", + " self._endpoint = None\n", + " self._security = None\n", + " self._impl_specific_info = None\n", + " self.discriminator = None\n", + " self.id = id\n", + " self.name = name\n", + " if description is not None:\n", + " self.description = description\n", + " self.type = type\n", + " self.protocol = protocol\n", + " self.version = version\n", + " self.endpoint = endpoint\n", + " self.security = security\n", + " if impl_specific_info is not None:\n", + " self.impl_specific_info = impl_specific_info\n", + " @property\n", + " def id(self):\n", + " return self._id\n", + " @id.setter\n", + " def id(self, id):\n", + " if id is None:\n", + " raise ValueError(\"Invalid value for `id`, must not be `None`\") # noqa: E501\n", + " self._id = id\n", + " @property\n", + " def name(self):\n", + " return self._name\n", + " @name.setter\n", + " def name(self, name):\n", + " if name is None:\n", + " raise ValueError(\"Invalid value for `name`, must not be `None`\") # noqa: E501\n", + " self._name = name\n", + " @property\n", + " def description(self):\n", + " return self._description\n", + " @description.setter\n", + " def description(self, description):\n", + " self._description = description\n", + " @property\n", + " def type(self):\n", + " return self._type\n", + " @type.setter\n", + " def type(self, type):\n", + " if type is None:\n", + " raise ValueError(\"Invalid value for `type`, must not be `None`\") # noqa: E501\n", + " self._type = type\n", + " @property\n", + " def protocol(self):\n", + " return self._protocol\n", + " @protocol.setter\n", + " def protocol(self, protocol):\n", + " if protocol is None:\n", + " raise ValueError(\"Invalid value for `protocol`, must not be `None`\") # noqa: E501\n", + " self._protocol = protocol\n", + " @property\n", + " def version(self):\n", + " return self._version\n", + " @version.setter\n", + " def version(self, version):\n", + " if version is None:\n", + " raise ValueError(\"Invalid value for `version`, must not be `None`\") # noqa: E501\n", + " self._version = version\n", + " @property\n", + " def endpoint(self):\n", + " return self._endpoint\n", + " @endpoint.setter\n", + " def endpoint(self, endpoint):\n", + " if endpoint is None:\n", + " raise ValueError(\"Invalid value for `endpoint`, must not be `None`\") # noqa: E501\n", + " self._endpoint = endpoint\n", + " @property\n", + " def security(self):\n", + " return self._security\n", + " @security.setter\n", + " def security(self, security):\n", + " if security is None:\n", + " raise ValueError(\"Invalid value for `security`, must not be `None`\") # noqa: E501\n", + " self._security = security\n", + " @property\n", + " def impl_specific_info(self):\n", + " return self._impl_specific_info\n", + " @impl_specific_info.setter\n", + " def impl_specific_info(self, impl_specific_info):\n", + " self._impl_specific_info = impl_specific_info\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(TransportInfo, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, TransportInfo):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class SecurityInfo(object):\n", + " swagger_types = {'o_auth2_info': 'SecurityInfoOAuth2Info'}\n", + " attribute_map = {'o_auth2_info': 'oAuth2Info'}\n", + " def __init__(self, o_auth2_info=None): # noqa: E501\n", + " self._o_auth2_info = None\n", + " self.discriminator = None\n", + " if o_auth2_info is not None:\n", + " self.o_auth2_info = o_auth2_info\n", + " @property\n", + " def o_auth2_info(self):\n", + " return self._o_auth2_info\n", + " @o_auth2_info.setter\n", + " def o_auth2_info(self, o_auth2_info):\n", + " self._o_auth2_info = o_auth2_info\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(SecurityInfo, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, SecurityInfo):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class SecurityInfoOAuth2Info(object):\n", + " swagger_types = {'grant_types': 'list[str]','token_endpoint': 'str'}\n", + " attribute_map = {'grant_types': 'grantTypes','token_endpoint': 'tokenEndpoint'}\n", + " def __init__(self, grant_types=None, token_endpoint=None): # noqa: E501\n", + " self._grant_types = None\n", + " self._token_endpoint = None\n", + " self.discriminator = None\n", + " self.grant_types = grant_types\n", + " self.token_endpoint = token_endpoint\n", + " @property\n", + " def grant_types(self):\n", + " return self._grant_types\n", + " @grant_types.setter\n", + " def grant_types(self, grant_types):\n", + " if grant_types is None:\n", + " raise ValueError(\"Invalid value for `grant_types`, must not be `None`\") # noqa: E501\n", + " self._grant_types = grant_types\n", + " @property\n", + " def token_endpoint(self):\n", + " return self._token_endpoint\n", + " @token_endpoint.setter\n", + " def token_endpoint(self, token_endpoint):\n", + " if token_endpoint is None:\n", + " raise ValueError(\"Invalid value for `token_endpoint`, must not be `None`\") # noqa: E501\n", + " self._token_endpoint = token_endpoint\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(SecurityInfoOAuth2Info, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, SecurityInfoOAuth2Info):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class OneOfTransportInfoEndpoint(object):\n", + " swagger_types = {}\n", + " attribute_map = {}\n", + " def __init__(self): # noqa: E501\n", + " self.discriminator = None\n", + " @property\n", + " def uris(self):\n", + " return self._uris\n", + " @uris.setter\n", + " def uris(self, uris):\n", + " self._uris = uris\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(OneOfappInstanceIdServicesBody, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, OneOfTransportInfoEndpoint):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class EndPointInfoUris(object):\n", + " swagger_types = {'_uris': 'list[str]'}\n", + " attribute_map = {'_uris': 'uris'}\n", + " def __init__(self, uris:list): # noqa: E501\n", + " self._uris = None\n", + " self.uris = uris\n", + " @property\n", + " def uris(self):\n", + " return self._uris\n", + " @uris.setter\n", + " def uris(self, uris):\n", + " self._uris = uris\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(EndPointInfoUris, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, EndPointInfoUris):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class EndPointInfoFqdn(object):\n", + " swagger_types = {'_fqdn': 'list[str]'}\n", + " attribute_map = {'_fqdn': 'fqdn'}\n", + " def __init__(self, fqdn:list): # noqa: E501\n", + " self._fqdn = None\n", + " self.fqdn = fqdn\n", + " @property\n", + " def fqdn(self):\n", + " return self._fqdn\n", + " @fqdn.setter\n", + " def fqdn(self, fqdn):\n", + " self._fqdn = fqdn\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(EndPointInfoFqdn, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, EndPointInfoFqdn):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class EndPointInfoAddress(object):\n", + " swagger_types = {'_host': 'str', '_port': 'int'}\n", + " attribute_map = {'_host': 'host', '_port': 'port'}\n", + " def __init__(self, host:str, port:list): # noqa: E501\n", + " self._host = None\n", + " self._port = None\n", + " self.host = host\n", + " self.port = port\n", + " @property\n", + " def host(self):\n", + " return self.host\n", + " @host.setter\n", + " def host(self, host):\n", + " self._host = host\n", + " @property\n", + " def port(self):\n", + " return self._port\n", + " @port.setter\n", + " def port(self, port):\n", + " self._port = qosport_kpi\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(EndPointInfoAddress, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, EndPointInfoAddress):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class EndPointInfoAddresses(object):\n", + " swagger_types = {'_addresses': 'list[EndPointInfoAddress]'}\n", + " attribute_map = {'_addresses': 'addresses'}\n", + " def __init__(self, addresses:list): # noqa: E501\n", + " self._addresses = None\n", + " self.addresses = addresses\n", + " @property\n", + " def addresses(self):\n", + " return self._addresses\n", + " @addresses.setter\n", + " def addresses(self, addresses):\n", + " self._addresses = addresses\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(lambda x: x.to_dict() if hasattr(x, 'to_dict') else x,value))\n", + " elif hasattr(value, 'to_dict'):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], 'to_dict') else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(EndPointInfoAddresses, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, EndPointInfoAddresses):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n", + "\n", + "class EndPointInfoAlternative(object):\n", + " swagger_types = {'alternative': 'object'}\n", + " attribute_map = {'alternative': 'alternative'}\n", + " def __init__(self, alternative=None): # noqa: E501\n", + " self._alternative = None\n", + " self.discriminator = None\n", + " self.alternative = alternative\n", + " @property\n", + " def alternative(self):\n", + " return self._alternative\n", + " @alternative.setter\n", + " def alternative(self, alternative):\n", + " if alternative is None:\n", + " raise ValueError(\"Invalid value for `alternative`, must not be `None`\") # noqa: E501\n", + " self._alternative = alternative\n", + " def to_dict(self):\n", + " result = {}\n", + " for attr, _ in six.iteritems(self.swagger_types):\n", + " value = getattr(self, attr)\n", + " if isinstance(value, list):\n", + " result[attr] = list(map(\n", + " lambda x: x.to_dict() if hasattr(x, \"to_dict\") else x,\n", + " value\n", + " ))\n", + " elif hasattr(value, \"to_dict\"):\n", + " result[attr] = value.to_dict()\n", + " elif isinstance(value, dict):\n", + " result[attr] = dict(map(\n", + " lambda item: (item[0], item[1].to_dict())\n", + " if hasattr(item[1], \"to_dict\") else item,\n", + " value.items()\n", + " ))\n", + " else:\n", + " result[attr] = value\n", + " if issubclass(EndPointInfoAlternative, dict):\n", + " for key, value in self.items():\n", + " result[key] = value\n", + " return result\n", + " def to_str(self):\n", + " return pprint.pformat(self.to_dict())\n", + " def __repr__(self):\n", + " return self.to_str()\n", + " def __eq__(self, other):\n", + " if not isinstance(other, EndPointInfoAlternative):\n", + " return False\n", + " return self.__dict__ == other.__dict__\n", + " def __ne__(self, other):\n", + " return not self == other\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create an application MEC service\n", + "\n", + "The function below is creating an application MEC services\n", + "\n", + "**Note:** This is call application MEC service in opposition of a standardized MEC service exposed by the MEC Sanbox such as MEC 013, MEC 030...\n", + "\n", + "**Reference:** ETSI GS MEC 011 V3.2.1 (2024-04) Clause 8.2.6.3.4 POST" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def create_mec_service(sandbox_name: str, app_inst_id: swagger_client.models.application_info.ApplicationInfo) -> object:\n", + " \"\"\"\n", + " Request to create a new application MEC service\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :param sub_id: The subscription identifier\n", + " :return The HTTP response, the response status and the headers on success, None otherwise\n", + " :see ETSI GS MEC 011 V3.2.1 (2024-04) Clause 8.2.6.3.4 POST\n", + " \"\"\"\n", + " global MEC_PLTF, CALLBACK_URI, logger, service_api\n", + "\n", + " logger.debug('>>> create_mec_service')\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/mec_service_mgmt/v1/applications/{app_inst_id}/services'\n", + " logger.debug('create_mec_service: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " path_params['app_inst_id'] = app_inst_id.id\n", + " # HTTP header `Accept`\n", + " header_params = {}\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " # Body request\n", + " callback = CALLBACK_URI + '/statistic/v1/quantity'\n", + " transport_info = TransportInfo(id=str(uuid.uuid4()), name='HTTP REST API', type='REST_HTTP', protocol='HTTP', version='2.0', security=SecurityInfo(), endpoint=OneOfTransportInfoEndpoint())\n", + " transport_info.endpoint.uris=[EndPointInfoUris(callback)]\n", + " category_ref = CategoryRef(href=callback, id=str(uuid.uuid4()), name='Demo', version='1.0.0')\n", + " appServiceInfo = ServiceInfo(ser_name='demo6 MEC Service', ser_category=category_ref, version='1.0.0', state='ACTIVE',transport_info=transport_info, serializer='JSON')\n", + " (result, status, headers) = service_api.call_api(url, 'POST', header_params=header_params, path_params=path_params, body=appServiceInfo, async_req=False)\n", + " return (result, status, headers['Location'])\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status, None)\n", + " # End of function create_mec_service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete an application MEC service\n", + "\n", + "The function below is deleting an application MEC services.\n", + "\n", + "**Reference:** ETSI GS MEC 011 V3.2.1 (2024-04) Clause 8.2.7.3.5 DELETE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def delete_mec_service(resource_url: str) -> int:\n", + " \"\"\"\n", + " Request to create a new application MEC service\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param app_inst_id: The MEC application instance identifier\n", + " :param sub_id: The subscription identifier\n", + " :return 0 on success, -1 otherwise\n", + " :see ETSI GS MEC 011 V3.2.1 (2024-04) Clause 8.2.7.3.5 DELETE\n", + " \"\"\"\n", + " global logger\n", + "\n", + " logger.debug('>>> delete_mec_subscription: resource_url: ' + resource_url)\n", + " try:\n", + " res = urllib3.util.parse_url(resource_url)\n", + " if res is None:\n", + " logger.error('delete_mec_subscription: Failed to paerse URL')\n", + " return -1\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " service_api.call_api(res.path, 'DELETE', header_params=header_params, async_req=False)\n", + " return 0\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return -1\n", + " # End of function delete_mec_service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Putting everything together\n", + "\n", + "The sequence is the following:\n", + "- Mec application setup\n", + "- Create new MEC service\n", + "- Send a request to our MEC service\n", + "- Delete newly created MEC service\n", + "- Mec application termination\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This is the fith sprint of our skeleton of our MEC application:\n", + " - Mec application setup\n", + " - Create new MEC service\n", + " - Send a request to our MEC service\n", + " - Delete newly created MEC service\n", + " - Mec application termination\n", + " \"\"\" \n", + " global LISTENER_IP, LISTENER_PORT, CALLBACK_URI, logger\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Start notification server in a daemonized thread\n", + " httpd = start_notification_server()\n", + "\n", + " # Setup the MEC application\n", + " sandbox_name, app_inst_id, sub_id = mec_app_setup()\n", + "\n", + " # Create the MEC service\n", + " result, status, mec_service_resource = create_mec_service(sandbox_name, app_inst_id)\n", + " if status != 201:\n", + " logger.error('Failed to create MEC service')\n", + " else:\n", + " logger.info('mec_service_resource: %s', mec_service_resource)\n", + "\n", + " # Send a request to our MEC service\n", + " logger.info('body: ' + str(result.data))\n", + " data = json.loads(result.data)\n", + " logger.info('data: %s', str(data))\n", + " logger.info('=============> Execute the command: curl --request GET %s/statistic/v1/quantity --header \"Accept: application/json\" --data \\'{\"time\":20180124,\"data1\":\"[1516752000,11590.6,11616.9,11590.4,11616.9,0.25202387,1516752060,11622.4,11651.7,11622.4,11644.6,1.03977764]\"}\\'', CALLBACK_URI)\n", + " time.sleep(60)\n", + "\n", + " # Stop notification server\n", + " stop_notification_server(httpd)\n", + "\n", + " # Delete the MEC servce\n", + " delete_mec_service(mec_service_resource)\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Support of CAPIF (3GPP TS 29.222: 3rd Generation Partnership Project; Technical Specification Group Core Network and Terminals; Common API Framework for 3GPP Northbound APIs)\n", + "\n", + "MEC-CAPIF support is described in ETSI GS MEC 011 (V3.2.1) Clause 9 [4]\n", + "\n", + "The sample code below illustrates the usage of MEC-CAPI endpoints:\n", + "- /service-apis/v1/allServiceAPIs\n", + "- /published-apis/v1/{apfId}/service-apis\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Getting all MEC services\n", + "\n", + "The code below illustrates how to use CAPIF '/service-apis/v1/allServiceAPIs' endpoint to retrieve the complete list of available MEC services.\n", + "\n", + "**Reference:** ETSI GS MEC 011 (V3.2.1) Clause 9.2.3 Resource: All published service APIs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def capif_get_all_mec_services(sandbox_name: str):\n", + " \"\"\"\n", + " To retrieves the MEC services using CAPIF endpoint\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :return The HTTP response and the response status on success, None otherwise\n", + " :see ETSI GS MEC 011 (V3.2.1) Clause 9\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> capif_get_all_mec_services: ' + sandbox_name)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/service-apis/v1/allServiceAPIs'\n", + " logger.debug('capif_get_all_mec_services: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " (result, status, headers) = service_api.call_api(url, 'GET', header_params=header_params, path_params=path_params, async_req=False)\n", + " return (result, status)\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status)\n", + " # End of capif_get_all_mec_services function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Getting MEC services for a specified MEC application instance ID\n", + "\n", + "The code below illustrates how to use CAPIF '/published-apis/v1/{apfId}/service-apis' endpoint to retrieve the complete list of MEC services for a specified MEC application instance ID (apfid).\n", + "\n", + "**Reference:** ETSI GS MEC 011 (V3.2.1) Table 9.2.4.2-1: Profiling of the URI variables" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def capif_get_mec_services(sandbox_name: str, apfId: str):\n", + " \"\"\"\n", + " To retrieves the MEC services using CAPIF endpoint\n", + " :param sandbox_name: The MEC Sandbox instance to use\n", + " :param apfId: The identifier of the entity that registers the service API\n", + " :return The HTTP response and the response status on success, None otherwise\n", + " :see ETSI GS MEC 011 (V3.2.1) Clause 9\n", + " \"\"\"\n", + " global MEC_PLTF, logger, service_api\n", + "\n", + " logger.debug('>>> capif_get_all_mec_services: ' + sandbox_name)\n", + " try:\n", + " url = '/{sandbox_name}/{mec_pltf}/published-apis/v1/{apfId}/service-apis'\n", + " logger.debug('capif_get_mec_services: url: ' + url)\n", + " path_params = {}\n", + " path_params['sandbox_name'] = sandbox_name\n", + " path_params['mec_pltf'] = MEC_PLTF\n", + " path_params['apfId'] = apfId\n", + " header_params = {}\n", + " # HTTP header `Accept`\n", + " header_params['Accept'] = 'application/json' # noqa: E501\n", + " # HTTP header `Content-Type`\n", + " header_params['Content-Type'] = 'application/json' # noqa: E501\n", + " (result, status, headers) = service_api.call_api(url, 'GET', header_params=header_params, path_params=path_params, async_req=False)\n", + " return (result, status)\n", + " except ApiException as e:\n", + " logger.error('Exception when calling call_api: %s\\n' % e)\n", + " return (None, status)\n", + " # End of capif_get_mec_services function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Putting evrythong together\n", + "\n", + "It is time now to create the our third iteration of our MEC application.\n", + "\n", + "The sequence is the following:\n", + "\n", + "- Login\n", + "- Activate a network scenario\n", + "- Create an application instance identifier\n", + "- Retrieve all MEC services (/service-apis/v1/allServiceAPIs)\n", + "- Retrieve MEC services for the newly created application instance identifier\n", + "- Delete our application instance identifier\n", + "- Deactivate a network scenario\n", + "- Logout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%script echo skipping\n", + "# Uncomment the ;line above to skip execution of this cell\n", + "def process_main():\n", + " \"\"\"\n", + " This code illustrates the usage of MEC-CAPI endpoints:\n", + " - Login\n", + " - Activate a network scenario\n", + " - Create an application instance identifier\n", + " - Retrieve all MEC services (/service-apis/v1/allServiceAPIs)\n", + " - Retrieve MEC services for the newly created application instance identifier\n", + " - Delete our application instance identifier\n", + " - Deactivate a network scenario\n", + " - Logout\n", + " \"\"\" \n", + " global LISTENER_IP, LISTENER_PORT, CALLBACK_URI, logger\n", + "\n", + " logger.debug('Starting at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " logger.debug('\\t pwd= ' + os.getcwd())\n", + "\n", + " # Setup the MEC application\n", + " sandbox_name, app_inst_id, sub_id = mec_app_setup()\n", + "\n", + " # Get the list of the MEC sevices using CAPIF endpoints\n", + " result, status = capif_get_all_mec_services(sandbox_name)\n", + " if status != 200:\n", + " logger.error('Failed to get the list of MEC services using CAPIF endpoint')\n", + " else:\n", + " logger.info('capif_get_all_mec_services: ' + str(result.data))\n", + "\n", + " # Get the list of the MEC sevices for our AppInstanceId using CAPIF endpoints\n", + " result, status = capif_get_mec_services(sandbox_name, app_inst_id.id)\n", + " if status != 200:\n", + " logger.error('Failed to get the list of MEC services for our AppInstanceId using CAPIF endpoint')\n", + " else:\n", + " logger.info('capif_get_mec_services: ' + str(result.data))\n", + "\n", + " # In the previous request, the list of services for our AppInstanceId is empty.\n", + " # Let's create a new MEC service\n", + " result, status, mec_service_resource = create_mec_service(sandbox_name, app_inst_id)\n", + " if status != 201:\n", + " logger.error('Failed to create MEC service')\n", + " else:\n", + " logger.info('mec_service_resource: %s', mec_service_resource)\n", + "\n", + " # Now, we can send a new request for services for our MEC application\n", + " # Get the list of the MEC sevices for our AppInstanceId using CAPIF endpoints\n", + " result, status = capif_get_mec_services(sandbox_name, app_inst_id.id)\n", + " if status != 200:\n", + " logger.error('Failed to get the list of MEC services for our AppInstanceId using CAPIF endpoint')\n", + " else:\n", + " logger.info('capif_get_mec_services: ' + str(result.data))\n", + " data = json.loads(result.data)\n", + " logger.info('serviceAPIDescriptions: ' + str(data))\n", + " # b'{\"serviceAPIDescriptions\":[{\"apiName\":\"demo6 MEC Service\",\"apiId\":\"6172de7d-ed42-4ba2-947a-a0db7cc8915e\",\"aefProfiles\":[{\"aefId\":\"3daa9b79-ba81-4a74-9668-df710dc68020\",\"versions\":[\"1.0.0\"],\"interfaceDescriptions\":{\"uris\":null,\"fqdn\":null,\"addresses\":null,\"alternative\":null},\"vendorSpecific-urn:etsi:mec:capifext:transport-info\":{\"name\":\"HTTP REST API\",\"type\":\"REST_HTTP\",\"protocol\":\"HTTP\",\"version\":\"2.0\",\"security\":{}}}],\"vendorSpecific-urn:etsi:mec:capifext:service-info\":{\"serializer\":\"JSON\",\"state\":\"ACTIVE\",\"scopeOfLocality\":\"MEC_HOST\",\"consumedLocalOnly\":true,\"isLocal\":true,\"category\":{\"href\":\"http://mec-platform2.etsi.org:31111/sandbox/v1/statistic/v1/quantity\",\"id\":\"98a5039d-2b7c-49b1-b3b1-45a6ebad2ea4\",\"name\":\"Demo\",\"version\":\"1.0.0\"}}}]}'\n", + " logger.info('apiId: ' + str(data['serviceAPIDescriptions'][0]['apiId'] + ' matching MEC serInstanceID'))\n", + " logger.info('aefId: ' + str(data['serviceAPIDescriptions'][0]['aefProfiles'][0]['aefId'] + ' matching MEC TransportInfo.Id\"'))\n", + "\n", + " # Delete the MEC servce\n", + " delete_mec_service(mec_service_resource)\n", + "\n", + " # Terminate the MEC application\n", + " mec_app_termination(sandbox_name, app_inst_id, sub_id)\n", + "\n", + " logger.debug('Stopped at ' + time.strftime('%Y%m%d-%H%M%S'))\n", + " # End of function process_main\n", + "\n", + "if __name__ == '__main__':\n", + " process_main()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Annexes\n", + "\n", + "## Annex A: How to use an existing MEC sandbox instance\n", + "\n", + "This case is used when the MEC Sandbox API is not used. The procedure is the following:\n", + "- Log to the MEC Sandbox using a WEB browser\n", + "- Select a network scenario\n", + "- Create a new application instance\n", + "\n", + "When it is done, the newly created application instance is used by your application when required. This application instance is usually passed to your application in the command line or using a configuration file\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Bibliography\n", + "\n", + "1. ETSI GS MEC 002 (V2.2.1) (01-2022): \"Multi-access Edge Computing (MEC); Phase 2: Use Cases and Requirements\".\n", + "2. ETSI GS MEC 010-1 (V1.1.1) (10-2017): \"Mobile Edge Computing (MEC); Mobile Edge Management; Part 1: System, host and platform management\".\n", + "3. ETSI GS MEC 010-2 (V2.2.1) (02-2022): \"Multi-access Edge Computing (MEC); MEC Management; Part 2: Application lifecycle, rules and requirements management\".\n", + "4. ETSI GS MEC 011 (V3.2.1) (09-2022): \"Multi-access Edge Computing (MEC); Edge Platform Application Enablement\".\n", + "5. ETSI GS MEC 012 (V2.2.1) (02-2022): \"Multi-access Edge Computing (MEC); Radio Network Information API\".\n", + "6. ETSI GS MEC 013 (V2.2.1) (01-2022): \"Multi-access Edge Computing (MEC); Location API\".\n", + "7. ETSI GS MEC 014 (V2.1.1) (03-2021): \"Multi-access Edge Computing (MEC); UE Identity API\".\n", + "8. ETSI GS MEC 015 (V2.1.1) (06-2020): \"Multi-Access Edge Computing (MEC); Traffic Management APIs\".\n", + "9. ETSI GS MEC 016 (V2.2.1) (04-2020): \"Multi-access Edge Computing (MEC); Device application interface\".\n", + "10. ETSI GS MEC 021 (V2.2.1) (02-2022): \"Multi-access Edge Computing (MEC); Application Mobility Service API\".\n", + "11. ETSI GS MEC 028 (V2.3.1) (07-2022): \"Multi-access Edge Computing (MEC); WLAN Access Information API\".\n", + "12. ETSI GS MEC 029 (V2.2.1) (01-2022): \"Multi-access Edge Computing (MEC); Fixed Access Information API\".\n", + "13. ETSI GS MEC 030 (V3.2.1) (05-2022): \"Multi-access Edge Computing (MEC); V2X Information Service API\".\n", + "14. ETSI GR MEC-DEC 025 (V2.1.1) (06-2019): \"Multi-access Edge Computing (MEC); MEC Testing Framework\".\n", + "15. ETSI GR MEC 001 (V3.1.1) (01-2022): \"Multi-access Edge Computing (MEC); Terminology\".\n", + "16. ETSI GR MEC 003 (V3.1.1): Multi-access Edge Computing (MEC);\n", + "17. 3GPP TS 29.222: 3rd Generation Partnership Project; Technical Specification Group Core Network and Terminals; Common API Framework for 3GPP Northbound APIs\n", + "Framework and Reference Architecture\n", + "18. [The Wiki MEC web site](https://www.etsi.org/technologies/multi-access-edge-computing)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/demo9/python/notebook/images/V2X Predicted QoS.jpg b/examples/demo9/python/notebook/images/V2X Predicted QoS.jpg new file mode 100644 index 0000000000000000000000000000000000000000..03a9b562a513afd148460fe210ead43657821bfd GIT binary patch literal 513891 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 z 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