How to send data to corresponding region's instance server? - load-balancing

Let's say I have three regions(eu,us,asia) that host the same app on the respective instance. I will register only one domain name for those same apps.
When a user requests from eu , I like to send data to eu region app server and vice versa.
Eg: user -> request -> example.com (from eu) -> send data to eu app
Eg: user -> request -> example.com (from us) -> send data to us app
Eg: user -> request -> example.com (from asia) -> send data to asia app
Can I set up like that by Load Balancer or something else?

Yes, you can do this with OCI DNS and traffic management via geolocation traffic steering policies. The steering policy should filter or prioritize DNS answers based on a query's continent geokey.
Example of a POST /steeringPolicies request body using the ROUTE_BY_GEO template:
{
"compartmentId": "ocid1...",
"displayName": "Geolocations mapped to answer pools",
"ttl": 30,
"healthCheckMonitorId": "ocid1...",
"template": "ROUTE_BY_GEO",
"answers": [
{
"name": "US Server 1",
"rtype": "A",
"rdata": "192.168.0.2",
"pool": "US"
},
{
"name": "US Server 2",
"rtype": "A",
"rdata": "192.168.0.3",
"pool": "US"
},
{
"name": "EU Server 1",
"rtype": "A",
"rdata": "192.168.0.4",
"pool": "EU"
},
{
"name": "EU Server 2",
"rtype": "A",
"rdata": "192.168.0.5",
"pool": "EU"
},
{
"name": "rest of world 1",
"rtype": "A",
"rdata": "203.0.113.2",
"pool": "Global"
},
{
"name": "rest of world 2",
"rtype": "A",
"rdata": "203.0.113.3",
"pool": "Global"
}
],
"rules": [
{
"ruleType": "FILTER",
"defaultAnswerData": [
{
"answerCondition": "answer.isDisabled != true",
"shouldKeep": true
}
]
},
{
"ruleType": "HEALTH"
},
{
"ruleType": "PRIORITY",
"cases": [
{
"caseCondition": "query.client.geoKey in (geoKey '6255149')",
"answerData": [
{
"answerCondition": "answer.pool == 'US'",
"value": 1
},
{
"answerCondition": "answer.pool == 'EU'",
"value": 2
},
{
"answerCondition": "answer.pool == 'Global'",
"value": 3
}
]
},
{
"caseCondition": "query.client.geokey in (geokey '6255148')",
"answerData": [
{
"answerCondition": "answer.pool == 'EU'",
"value": 1
},
{
"answerCondition": "answer.pool == 'US'",
"value": 2
},
{
"answerCondition": "answer.pool == 'Global'",
"value": 3
}
]
},
{
"answerData": [
{
"answerCondition": "answer.pool == 'Global'",
"value": 1
},
{
"answerCondition": "answer.pool == 'US'",
"value": 2
},
{
"answerCondition": "answer.pool == 'EU'",
"value": 3
}
]
}
]
},
{
"ruleType": "LIMIT",
"defaultCount": 1
}
]
}
-- Traffic Management Steering Policies API Guide, Create Steering Policies Using Templates

Related

Swagger API having different response with the change of Optional Parameters

I am trying to create the OAS Swagger documentation for an existing API where the response for the API is changing on the basis of Query parameter. I am struggling to document this in a developer friendly way, so need some assistance. Below is the complete scenario for your reference.
EndPoint 1 : /order?expand=false
/order?expand=false
{
"orderNo": "12345",
"orderDetail": "Description of Order",
"orderMarket": {
"id": "UK"
},
"brandOrderStatus": {
"id": "LLA"
}
}
Endpoint 2 : /order?expand=true
{
"orderNo": "12345",
"orderDetail": "Description of Order",
"orderMarket": {
"id": "UK",
"descr": "United Kingdom",
"lang": "en-GB"
},
"brandOrderStatus": {
"id": "LLA",
"descr": "Some Status Description",
"lang": "en-GB"
}
}
Endpoint 3 : /order?expand=true&include=feature
{
"orderNo": "12345",
"orderDetail": "Description of Order",
"orderMarket": {
"id": "UK",
"descr": "United Kingdom",
"lang": "en-GB"
},
"brandOrderStatus": {
"id": "LLA",
"descr": "Some Status Description",
"lang": "en-GB"
}
"_embedded": {
"features": [
{
"id": "AJS",
"type": "FeatureType",
"descr": "FeatureDescription",
"prices": [
{
"type": "msrpNetPrice",
"amount": 0.00,
"currency": "GBP"
}
],
"group": "null"
}
]
}
}
I tried using OneOf, but don't really think that will work in this case as the structure is changing with every optional parameter.
Any thoughts as how this can be documented in Swagger documentation ? Or any other idea to get this documented.

JSON element extraction from response based on scenario outline examples or external file

This is my api response. Want to extract the value of the Id based on the displayNumber. This display number is a given in the list of values in examples/csv file.
{
"Acc": [
{
"Id": "2b765368696b3441673633325",
"code": "SGD",
"val": 406030.83,
"displayNumber": "8957",
"curval": 406030.83
},
{
"Id": "4e676269685a73787472355776764b50717a4",
"code": "GBP",
"val": 22.68,
"displayNumber": "1881",
"curval": 22.68
},
{
"Id": "526e666d65366e67626244626e6266467",
"code": "SGD",
"val": 38404.44,
"displayNumber": "1004",
"curval": 38404.44
},
],
"combinations": [
{
"displayNumber": "3444",
"Code": "SGD",
"Ids": [
{
"Id": "2b765368696b34416736333254462"
},
{
"Id": "4e676269685a7378747235577"
},
{
"Id": "526e666d65366e6762624d"
}
],
"destId": "3678434b643530456962435272d",
"curval": 3.85
},
{
"displayNumber": "8957",
"code": "SGD",
"Ids": [
{
"Id": "3678434b6435304569624357"
},
{
"Id": "4e676269685a73787472355776764b50717a4"
},
{
"Id": "526e666d65366e67626244626e62664679"
}
],
"destId": "2b765368696b344167363332544",
"curval": 406030.83
},
{
"displayNumber": "1881",
"code": "GBP",
"Ids": [
{
"Id": "3678434b643530456962435275"
},
{
"Id": "2b765368696b3441673"
},
{
"Id": "526e666d65366e67626244626e626"
}
],
"destId": "4e676269685a7378747d",
"curval": 22.68
},
]
}
Examples
|displayNumber|
|8957|
|3498|
|4943|
Below expression works if i give the value
* def tempid = response
* def fromAccount = get[0] tempid.Acc[?(#.displayNumber==8957].Id
I'm not sure how to make this comparison value (i.e. 1881) as a variable which can be read from examples (scenario outline) or a csv file. Went through the documentation, which recommends, karate filters or maps. However, not able to follow how to implement.
You almost got it :-). This is the way you want to solve this
Scenario Outline: Testing SO question for Navneeth
* def tempid = response
* def fromAccount = get[0] tempid.Acc[?(#.displayNumber == <displayNumber>)]
* print fromAccount
Examples:
|displayNumber|
|8957|
|1881|
|3444|
You need to pass the placeholder in examples as -
'<displayNumber>'

eBay API issues - cannot publish an offer

All of the following is being performed in eBay's API sandbox.
I am attempting to list an item by using the inventory API. Specifically, I have created an inventory item and a relevant offer for that item. When I make a POST request to the publish offer endpoint, I get the following error:
{
"errors": [
{
"errorId": 25016,
"domain": "API_INVENTORY",
"subdomain": "Selling",
"category": "REQUEST",
"message": "The title value is invalid. Seller Provided Title Value is missing."
},
{
"errorId": 25002,
"domain": "API_INVENTORY",
"subdomain": "Selling",
"category": "REQUEST",
"message": "A user error has occurred. The duration \"GTC\" day(s) is not available for this listing type, or invalid for category \"49996\".",
"parameters": [
{
"name": "0",
"value": "GTC"
},
{
"name": "1",
"value": "49996"
}
]
}
]
}
I can't see any reference in any of the API documentation to a "Seller Provided Title". The duration error is also confusing as the API says it only supports "GTC" listings. The product has a title so it must be in reference to something else.
My inventory item is as follows:
{
"sku": "13725",
"product": {
"title": "Harley Davidson bike",
"aspects": {
"Year": [
"2016"
],
"Model": [
"Road Glide Special"
],
"Manufacurer": [
"Harley-Davidson®"
],
"Type": [
"Touring"
],
"For Sale By": [
"Dealer"
],
"Vehicle Title": [
"Clear"
],
"Mileage": [
"13393"
],
"VIN (Vehicle Identification Number)": [
"1HD1KTM10GB627264"
],
"Color": [
"Black Quartz"
]
},
"description": "Item description goes here",
"imageUrls": [
"https://dw4i9za0jmiyk.cloudfront.net/2018/01/12/pre_ic60e5df584b870c3d2a55c86800eede_70618b24eb08.jpg"
]
},
"condition": "USED_EXCELLENT",
"availability": {
"pickupAtLocationAvailability": [
{
"quantity": 1,
"merchantLocationKey": "425",
"availabilityType": "IN_STOCK",
"fulfillmentTime": {
"value": 1,
"unit": "DAY"
}
}
]
}
}
And my offer object is as follows:
{
"offerId": "5852159010",
"sku": "13725",
"marketplaceId": "EBAY_MOTORS",
"format": "FIXED_PRICE",
"availableQuantity": 0,
"pricingSummary": {
"price": {
"value": "18294.0",
"currency": "USD"
}
},
"listingPolicies": {
"paymentPolicyId": "5807565000",
"fulfillmentPolicyId": "5806186000"
},
"categoryId": "49996",
"merchantLocationKey": "425",
"tax": {
"applyTax": false
},
"status": "UNPUBLISHED",
"eBayPlusEligible": false
}
I had similar issues on sandbox, and came to the conculsion it was broken.
They also have some limits on only certain categories working.
Have you tried it agains the live API, I have found this to be far more reliable, ignoring the fact doing development work live is dangerous!
For your info here is my working code offer:
inventory_template = {
"availability": {
"shipToLocationAvailability": {
"quantity": product.quantity_available
}
},
"condition": "NEW",
"product": {
"aspects": {spec.name: [spec.value] for spec in product.specifics},
"brand": product.product_brand,
"description": product.product_description,
"imageUrls": [
"https://ebay.mydomain.co.uk/{}".format(img.image_link) for img in product.images],
"mpn": product.product_mpn,
"title": product.product_title,
"upc": [
product.product_upc,
],
"ean": [
product.product_ean,
],
# "epid": "string"
},
"sku": sku,
}
offer_body = {
"availableQuantity": offer.available_quantity,
"categoryId": offer.category_id,
"listingDescription": html,
"listingPolicies": {
"paymentPolicyId": offer.payment_policy_id,
"returnPolicyId": offer.return_policy_id,
"fulfillmentPolicyId": offer.fulfillment_policy_id,
},
"merchantLocationKey": offer.merchant_location_key,
"pricingSummary": {
"price": {
"value": offer.summary_price_value,
"currency": offer.summary_price_currency
}
},
"sku": offer.sku,
"marketplaceId": offer.marketplace_id,
"format": offer.format
}
the offer.available_quantity etc are items from my database, its the structure I'm showing.

How to update existing Knowledgebase using QnA Maker API v4.0?

I've successfully created my Knowledgebase using API.
But I forgot to add some alternative questions and metadata for one of the pairs.
I've noticed PATH method in the API to update the Knowledebase, so updating kb is supported.
I've created a payload which looked like this:
{
"add": {
},
"delete": {
},
"update": {
"qnaList": [
{
"id": 1,
"answer": "Answer",
"source": "link_to_source",
"questions": [
"Question 1?",
"Question 2?"
],
"metadata": [
{
"name": "oldMetadata",
"value": "oldMetadata"
},
{
"name": "newlyAddedMetaData",
"value": "newlyAddedMetaData"
}
]
}]}
}
I get back the following response HTTP 202 Accepted:
{
"operationState": "NotStarted",
"createdTimestamp": "2018-05-21T07:46:52Z",
"lastActionTimestamp": "2018-05-21T07:46:52Z",
"userId": "user_uuid",
"operationId": "operation_uuid"
}
So, looks like it worked. But in reality, this request doesn't take any affect.
When I check operation details, it returns me the following:
{
"operationState": "Succeeded",
"createdTimestamp": "2018-05-21T07:46:52Z",
"lastActionTimestamp": "2018-05-21T07:46:54Z",
"resourceLocation": "/knowledgebases/kb_uuid",
"userId": "user_uuid",
"operationId": "operation_uuid"
}
What am I doing wrong? And how should I update my kb via API properly?
Please help
I had the same problem, I discovered that it was necessary to have all the data of the json even if they were not used.
In your case you need "name" and "urls" in the "update" section and "Delete" in "update/qnaList/questions" section:
{
"add": {},
"delete": {},
"update": {
"name": "nameofKbBase", //this
"qnaList": [
{
"id": 2370,
"answer": "DemoAnswerEdit",
"source": "CustomSource",
"questions": {
"add": [
"DemoQuestionEdit"
],
"delete": [] //this
},
"metadata": { }
}
],
"urls": [] //this
}
}

Transform JSON response with lodash

I'm new in lodash (v3.10.1), and having a hard time understanding.
Hope someone can help.
I have an input something like this:
{
{"id":1,"name":"Matthew","company":{"id":1,"name":"abc","industry":{"id":5,"name":"Medical"}}},
{"id":2,"name":"Mark","company":{"id":1,"name":"abc","industry":{"id":5,"name":"Medical"}}},
{"id":3,"name":"Luke","company":{"id":1,"name":"abc","industry":{"id":5,"name":"Medical"}}},
{"id":4,"name":"John","company":{"id":1,"name":"abc","industry":{"id":5,"name":"Medical"}}},
{"id":5,"name":"Paul","company":{"id":1,"name":"abc","industry":{"id":5,"name":"Medical"}}}
];
I would like to output this or close to this:
{
"industries": [
{
"industry":{
"id":5,
"name":"Medical",
"companies": [
{
"company":{
"id":1,
"name":"abc",
"employees": [
{"id":1,"name":"Matthew"},
{"id":2,"name":"Mark"},
{"id":3,"name":"Luke"},
{"id":4,"name":"John"},
{"id":5,"name":"Paul"}
]
}
}
]
}
}
]
}
Here's something that gets you close to what you want. I structured the output to be an object instead of an array. You don't need the industries or industry properties in your example output. The output structure looks like this:
{
"industry name": {
"id": "id of industry",
"companies": [
{
"company name": "name of company",
"id": "id of company",
"employees": [
{
"id": "id of company",
"name": "name of employee"
}
]
}
]
}
}
I use the _.chain function to wrap the collection with a lodash wrapper object. This enables me to explicitly chain lodash functions.
From there, I use the _.groupBy function to group elements of the collection by their industry name. Since I'm chaining, I don't have to pass in the array again to the function. It's implicitly passed via the lodash wrapper. The second argument of the _.groupBy is the path to the value I want to group elements by. In this case, it's the path to the industry name: company.industry.name. _.groupBy returns an object with each employee grouped by their industry (industries are keys for this object).
I then do use _.transform to transform each industry object. _.transform is essentially _.reduce except that the results returned from the _.transform function is always an object.
The function passed to the _.transform function gets executed against each key/value pair in the object. In the function, I use _.groupBy again to group employees by company. Based off the results of _.groupBy, I map the values to the final structure I want for each employee object.
I then call the _.value function because I want to unwrap the output collection from the lodash wrapper object.
I hope this made sense. If it doesn't, I highly recommend reading Lo-Dash Essentials. After reading the book, I finally got why lodash is so useful.
"use strict";
var _ = require('lodash');
var emps = [
{ "id": 1, "name": "Matthew", "company": { "id": 1, "name": "abc", "industry": { "id": 5, "name": "Medical" } } },
{ "id": 2, "name": "Mark", "company": { "id": 1, "name": "abc", "industry": { "id": 5, "name": "Medical" } } },
{ "id": 3, "name": "Luke", "company": { "id": 1, "name": "abc", "industry": { "id": 5, "name": "Medical" } } },
{ "id": 4, "name": "John", "company": { "id": 1, "name": "abc", "industry": { "id": 5, "name": "Medical" } } },
{ "id": 5, "name": "Paul", "company": { "id": 1, "name": "abc", "industry": { "id": 5, "name": "Medical" } } }
];
var result = _.chain(emps)
.groupBy("company.industry.name")
.transform(function(result, employees, industry) {
result[industry] = {};
result[industry].id = _.get(employees[0], "company.industry.id");
result[ industry ][ 'companies' ] = _.map(_.groupBy(employees, "company.name"), function( employees, company ) {
return {
company: company,
id: _.get(employees[ 0 ], 'company.id'),
employees: _.map(employees, _.partialRight(_.pick, [ 'id', 'name' ]))
};
});
return result;
})
.value();
Results from your example are as follows:
{
"Medical": {
"id": 5,
"companies": [
{
"company": "abc",
"id": 1,
"employees": [
{
"id": 1,
"name": "Matthew"
},
{
"id": 2,
"name": "Mark"
},
{
"id": 3,
"name": "Luke"
},
{
"id": 4,
"name": "John"
},
{
"id": 5,
"name": "Paul"
}
]
}
]
}
}
If you ever wanted the exact same structure as in the questions, I solved it using the jsonata library:
(
/* lets flatten it out for ease of accessing the properties*/
$step1 := $ ~> | $ |
{
"employee_id": id,
"employee_name": name,
"company_id": company.id,
"company_name": company.name,
"industry_id": company.industry.id,
"industry_name": company.industry.name
},
["company", "id", "name"] |;
/* now the magic begins*/
$step2 := {
"industries":
[($step1{
"industry" & $string(industry_id): ${
"id": $distinct(industry_id)#$I,
"name": $distinct(industry_name),
"companies": [({
"company" & $string(company_id): {
"id": $distinct(company_id),
"name": $distinct(company_name),
"employees": [$.{
"id": $distinct(employee_id),
"name": $distinct(employee_name)
}]
}
} ~> $each(function($v){ {"company": $v} }))]
}
} ~> $each(function($v){ {"industry": $v} }))]
};
)
You can see it in action on the live demo site: https://try.jsonata.org/VvW4uTRz_