Thrift Rate Limiting with Envoy - istio

I'm extending Istio to provide Thrift features. The Istio component I'm working on right now is Pilot (Envoy config service). I've extended it with basic Thrift routing so that it can provide an Envoy configuration to route a listener to the correct cluster. My development environment looks something like:
Now I'm trying to add rate limiting. I'm following the docs. I've patched my config with a RouteAction that doesn't get applied, because there is no rate limit filter. This works fine, and passes traffic as before:
...
{
"filters": [
{
"name": "envoy.filters.network.thrift_proxy",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.network.thrift_proxy.v2alpha1.ThriftProxy",
"stat_prefix": "10.97.28.169_9090",
"transport": "HEADER",
"protocol": "BINARY",
"route_config": {
"name": "outbound|9090||backend.default.svc.cluster.local",
"routes": [
{
"match": {
"method_name": ""
},
"route": {
"cluster": "outbound|9090||backend.default.svc.cluster.local",
"rate_limits": [
{
"actions": [
{
"request_headers": {
"header_name": ":method-name",
"descriptor_key": "method-name"
}
}
]
}
]
}
}
]
}
}
}
]
}
],
"deprecated_v1": {
"bind_to_port": false
},
"listener_filters_timeout": "0.100s",
"traffic_direction": "OUTBOUND",
"continue_on_listener_filters_timeout": true
},
"last_updated": "2019-10-30T16:26:39.203Z"
},
...
I've built a function to create an envoy.filters.thrift.rate_limit filter that makes Envoy to call the rate limit service I've set up (I've tried both GoogleGrpc and EnvoyGrpc):
func buildThriftRatelimit(ratelimitServiceUri, domain string) *thrift_ratelimit.RateLimit {
var thriftRateLimit *thrift_ratelimit.RateLimit
timeout := 2000 * time.Millisecond
thriftRateLimit = &thrift_ratelimit.RateLimit{
Domain: domain,
Timeout: &timeout,
FailureModeDeny: false,
RateLimitService: &ratelimit.RateLimitServiceConfig{
GrpcService: &core.GrpcService{
TargetSpecifier: &core.GrpcService_GoogleGrpc_{
GoogleGrpc: &core.GrpcService_GoogleGrpc{
StatPrefix: ratelimitServiceUri,
TargetUri: ratelimitServiceUri,
},
},
},
},
}
thriftRateLimit.Validate()
if err := thriftRateLimit.Validate(); err != nil {
panic(err)
}
return thriftRateLimit
}
Which produces:
...
{
"filters": [
{
"name": "envoy.filters.network.thrift_proxy",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.network.thrift_proxy.v2alpha1.ThriftProxy",
"stat_prefix": "10.97.28.169_9090",
"transport": "HEADER",
"protocol": "BINARY",
"route_config": {
"name": "outbound|9090||backend.default.svc.cluster.local",
"routes": [
{
"match": {
"method_name": ""
},
"route": {
"cluster": "outbound|9090||backend.default.svc.cluster.local",
"rate_limits": [
{
"actions": [
{
"request_headers": {
"header_name": ":method-name",
"descriptor_key": "method-name"
}
}
]
}
]
}
}
]
},
"thrift_filters": [
{
"name": "envoy.filters.thrift.rate_limit",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.thrift.rate_limit.v2alpha1.RateLimit",
"domain": "backend.default.svc.cluster.local",
"timeout": "2s",
"rate_limit_service": {
"grpc_service": {
"google_grpc": {
"target_uri": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80",
"stat_prefix": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80"
}
}
}
}
}
]
}
}
]
}
],
"deprecated_v1": {
"bind_to_port": false
},
"listener_filters_timeout": "0.100s",
"traffic_direction": "OUTBOUND",
"continue_on_listener_filters_timeout": true
},
"last_updated": "2019-10-30T16:26:39.203Z"
},
...
When the rate limit filter is applied, connections to the backend die and no error is returned to the client or displayed in Envoy's logs.

If Thrift filters are provided, you need to add the Router filter as the last filter in the chain like so:
...
{
"filters": [
{
"name": "envoy.filters.network.thrift_proxy",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.network.thrift_proxy.v2alpha1.ThriftProxy",
"stat_prefix": "10.97.28.169_9090",
"transport": "HEADER",
"protocol": "BINARY",
"route_config": {
"name": "outbound|9090||backend.default.svc.cluster.local",
"routes": [
{
"match": {
"method_name": ""
},
"route": {
"cluster": "outbound|9090||backend.default.svc.cluster.local",
"rate_limits": [
{
"actions": [
{
"request_headers": {
"header_name": ":method-name",
"descriptor_key": "method-name"
}
}
]
}
]
}
}
]
},
"thrift_filters": [
{
"name": "envoy.filters.thrift.rate_limit",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.thrift.rate_limit.v2alpha1.RateLimit",
"domain": "backend.default.svc.cluster.local",
"timeout": "2s",
"rate_limit_service": {
"grpc_service": {
"google_grpc": {
"target_uri": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80",
"stat_prefix": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80"
}
}
}
}
},
{
"name": "envoy.filters.thrift.router"
}
]
}
}
]
}
],
"deprecated_v1": {
"bind_to_port": false
},
"listener_filters_timeout": "0.100s",
"traffic_direction": "OUTBOUND",
"continue_on_listener_filters_timeout": true
},
"last_updated": "2019-10-30T16:26:39.203Z"
},
...

Related

How to set or not set audio selector in AWS media convert?

I got this error, when creating job for AWS media convert:
Invalid selector_sequence_id [0] specified for audio_description [1].
I do not even need sound for my output mp4 video.
My intention is to loop for 2 second an image (png or jpg) and add a fade effect for the first frames.
How would you change the sent json?
{
"middlewareStack": {},
"input": {
"Queue": "arn:aws:mediaconvert:eu-central-1:634617701827:queues/Default",
"UserMetadata": {},
"Role": "arn:aws:iam::634617701827:role/service-role/MediaConvert_Default_Role",
"Settings": {
"TimecodeConfig": {
"Anchor": "00:00:00:00",
"Source": "EMBEDDED"
},
"OutputGroups": [
{
"Name": "File Group",
"Outputs": [
{
"Preset": "createPromoVideo",
"Extension": "mp4",
"NameModifier": "_fade",
"VideoDescription": {
"CodecSettings": {
"FilterGraph": "fade=out:150:30"
},
"ScalingBehavior": "DEFAULT",
"TimecodeInsertion": "DISABLED",
"AntiAlias": "ENABLED",
"Sharpness": 50,
"Height": 1080,
"Width": 1080
},
"AudioDescriptions": [
{
"AudioSelector": {
"SelectorSettings": [
{
"AudioSelectorName": "Default"
}
]
},
"CodecSettings": {
"Codec": "AAC",
"AacSettings": {
"Bitrate": 96000,
"CodingMode": "CODING_MODE_2_0",
"SampleRate": 48000
}
}
}
]
}
],
"OutputGroupSettings": {
"Type": "FILE_GROUP_SETTINGS",
"FileGroupSettings": {
"Destination": "s3://t44-post-cover/8fui.mp4",
"DestinationSettings": {
"S3Settings": {
"AccessControl": {
"CannedAcl": "PUBLIC_READ"
}
}
}
}
}
}
],
"Inputs": [
{
"FileInput": "s3://t44-post-cover/8fui",
"VideoSelector": {
"ColorSpace": "FOLLOW"
},
"FilterEnable": "AUTO",
"TimecodeSource": "ZEROBASED",
"InputClippings": [
{
"StartTimecode": "00:00:00:00",
"EndTimecode": "00:00:02:00"
}
],
"FilterGraph": "fade=in:0:30",
"AudioSelectors": {
"Default": {
"DefaultSelection": "DEFAULT"
}
}
}
]
},
"AccelerationSettings": {
"Mode": "DISABLED"
},
"StatusUpdateInterval": "SECONDS_60",
"Priority": 0
}
}
AWS MediaConvert requires you to have at least one Audio Selector.
Just provide it with this simple one:
"Inputs": [
...
{
"AudioSelectors": {
"Audio Selector 1": {
"Offset": 0,
"DefaultSelection": "DEFAULT",
"SelectorType": "LANGUAGE_CODE",
"ProgramSelection": 1,
"LanguageCode": "ENM"
}
},
...
},
UPDATE:
A more barebones one:
"Inputs": [
...
{
"AudioSelectors": {
"Audio Selector 1": {
DefaultSelection: 'DEFAULT',
},
}
},
...
},

Not able to create preview for customized asset feed spec preview

I am using the following asset_feed_spec bean:
"asset_feed_spec": {
"ad_formats": [
"CAROUSEL_IMAGE"
],
"asset_customization_rules": [
{
"customization_spec": {
"publisher_platforms": [
"facebook"
],
"facebook_positions": [
"story"
]
},
"carousel_label": {
"name": "labelStory"
}
},
{
"customization_spec": {
"publisher_platforms": [
"facebook"
],
"facebook_positions": [
"feed"
]
},
"carousel_label": {
"name": "labelNormal"
}
},
{
"customization_spec": {
"publisher_platforms": [
"instagram"
],
"instagram_positions": [
"story"
]
},
"carousel_label": {
"name": "labelStory"
}
},
{
"customization_spec": {
"publisher_platforms": [
"instagram"
],
"instagram_positions": [
"stream"
]
},
"carousel_label": {
"name": "labelNormal"
}
}
],
"bodies": [
{
"text": "hiiiiiiiiiiiiiiii123"
}
],
"call_to_action_types": [
"LEARN_MORE"
],
"carousels": [
{
"adlabels": [
{
"name": "labelNormal"
}
],
"child_attachments": [
{
"description": "testing",
"picture": "<picture_url_here>",
"link": "www.google.com",
"name": "test"
},
{
"description": "testing",
"picture": "<picture_url_here>",
"link": "www.google.com",
"name": "test"
},
{
"description": "testing",
"picture": "<picture_url_here>",
"link": "www.google.com",
"name": "test"
}
]
}
],
"descriptions": [
{
"text": "test"
}
],
"link_urls": [
{
"website_url": "hi.com"
}
],
"titles": [
{
"text": "hiiiiiiiiiiiiiiii123"
}
]
},
"object_story_spec": {
"page_id": "<page_id>"
}
}

Logstash output to ES gives me error code '400'

Can I please ask for a help?
I am using following:
logstash v.6.1.5
AWS ES v.7.9
I have following logstash output:
elasticsearch {
hosts => ["es_host"]
ssl => true
user => "user"
password => "password"
template => '/etc/logstash/conf.d/template-default.json'
template_overwrite => true
index => "log-default-%{+yyyy-MM-dd}"
ilm_enabled => false
}
And this is the template:
"order": 1,
"index_patterns": [
"log-default-*",
"log-http-*"
],
"settings": {
"number_of_shards": 6,
"number_of_replicas": 2
},
"mappings": {
"_default_": {
"dynamic_templates": [
{
"ips": {
"match_pattern": "regex",
"match": "^(?:orig_)?(?:src|dst)ip$",
"mapping": {
"type": "ip"
}
}
},
{
"strings": {
"match": "*",
"unmatch": "*message",
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
}
When I start logstash, I receive an error as per the following. Does anyone have an idea what could be wrong?
[ERROR][logstash.outputs.elasticsearch] Failed to install template. {:message=>"Got response code '400' contacting Elasticsearch at URL 'https://es-host:443/_template/logstash'
Your template-default.json file should contain this, i.e. remove the _default_ key and you're good to go.
{
"order": 1,
"index_patterns": [
"log-default-*",
"log-http-*"
],
"settings": {
"number_of_shards": 6,
"number_of_replicas": 2
},
"mappings": {
"dynamic_templates": [
{
"ips": {
"match_pattern": "regex",
"match": "^(?:orig_)?(?:src|dst)ip$",
"mapping": {
"type": "ip"
}
}
},
{
"strings": {
"match": "*",
"unmatch": "*message",
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}

Request body variable from JSON not accepting integer values

My sample JSON file for postman runner:
[ { "name": "runner", "hitler_id": "4006abc", "year": "2017", "boolean": "false", "expected": 717962 } ]
Pre request script:
var member = data.name; var booking = data.boolean; var fyyear = data.year; var sid = data.hitler_id;
console.log(data.name); console.log(data.boolean); console.log(data.year); console.log(data.hitler_id);
Body with parameters:
{ "size": 0, "query": { "bool": { "filter": [ { "terms": { "name": [ "{{name}}" ] } }, { "terms": { "salesman_id": [ "{{sid}}" ] } }, { "terms": { "fyyear": [ "{{fyyear}}" ] } }, { "terms": { "boolean": [ "{{boolean}}" ] } } ] } }, "aggs": { "year": { "terms": { "field": "year" }, "aggs": { "value": { "sum": { "field": "value" } } } } } }
For only string variables are accepted - name and boolean fields are working and the value is populated
for the other two, the variable values are not passed.
The variables are not used in your request body that way.
Either you have to store them in environment oder global variables via
pm.globals.set("variable_key", variable_value)
pm.environment.set("variable_key", "variable_value");
or just skip the pre-request script if you just want to use your data and reference the fields directly in your body:
{
"size": 0,
"query": {
"bool": {
"filter": [
{
"terms": {
"name": [
"{{name}}"
]
}
},
{
"terms": {
"salesman_id": [
"{{hitler_id}}"
]
}
},
{
"terms": {
"fyyear": [
{{year}}
]
}
},
{
"terms": {
"boolean": [
{{boolean}}
]
}
}
]
}
},
"aggs": {
"year": {
"terms": {
"field": "year"
},
"aggs": {
"value": {
"sum": {
"field": "value"
}
}
}
}
}
}
However take care you're storing the values in your data file. You stored the bool and the year as strings". But they should be represented as you already did for the "expected" var.

Unable to use more than two Action Packages to create multiple custom actions

I followed this link :
https://developers.google.com/assistant/sdk/guides/service/python/extend/custom-actions
And I successfully create three actions files. and it works individually. but when I test all together like deploying three action packages:
./gactions update --action_package MqttAct.json --action_package action.json --action_package MesureTemp.json --project rpi3-0001-ga-******
I found that only two packages will work. it's like we can't have more than two action packages?
I'm surprised you can even deploy two packages at the same time. The idea is that you have one action package, which can contain a variety of actions merged together.
Here is a merged action package, based on the documentation:
{
"manifest": {
"displayName": "Blinky light",
"invocationName": "Blinky light",
"category": "PRODUCTIVITY"
},
"actions": [
{
"name": "com.example.actions.BlinkLight",
"availability": {
"deviceClasses": [
{
"assistantSdkDevice": {}
}
]
},
"intent": {
"name": "com.example.intents.BlinkLight",
"parameters": [
{
"name": "number",
"type": "SchemaOrg_Number"
},
{
"name": "speed",
"type": "Speed"
}
],
"trigger": {
"queryPatterns": [
"blink ($Speed:speed)? $SchemaOrg_Number:number times",
"blink $SchemaOrg_Number:number times ($Speed:speed)?"
]
}
},
"fulfillment": {
"staticFulfillment": {
"templatedResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Blinking $number times"
}
},
{
"deviceExecution": {
"command": "com.example.commands.BlinkLight",
"params": {
"speed": "$speed",
"number": "$number"
}
}
}
]
}
}
}
},
{
"name": "com.example.actions.BlonkLight",
"availability": {
"deviceClasses": [
{
"assistantSdkDevice": {}
}
]
},
"intent": {
"name": "com.example.intents.BlonkLight",
"parameters": [
{
"name": "number",
"type": "SchemaOrg_Number"
},
{
"name": "speed",
"type": "Speed"
}
],
"trigger": {
"queryPatterns": [
"blonk ($Speed:speed)? $SchemaOrg_Number:number times",
"blonk $SchemaOrg_Number:number times ($Speed:speed)?"
]
}
},
"fulfillment": {
"staticFulfillment": {
"templatedResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Blonking $number times"
}
},
{
"deviceExecution": {
"command": "com.example.commands.BlonkLight",
"params": {
"speed": "$speed",
"number": "$number"
}
}
}
]
}
}
}
}
],
"types": [
{
"name": "$Speed",
"entities": [
{
"key": "slowly",
"synonyms": [
"slowly",
"slow"
]
},
{
"key": "normally",
"synonyms": [
"normally",
"regular"
]
},
{
"key": "quickly",
"synonyms": [
"quickly",
"fast",
"quick"
]
}
]
}
]
}