Sure, but it’s more or less what @ed.snible was showing, so perhaps the error you have is due to the wasm code, not the EnvoyFilter resource.
Here’s my EnvoyFilter:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: ui-examplefilter
namespace: default
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: envoy.http_connection_manager
subFilter:
name: envoy.router
patch:
operation: INSERT_BEFORE
value:
name: example-filter
typed_config:
'@type': type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
value:
config:
# 'configuration' available at root_context.getConfiguration()
configuration:
'@type': type.googleapis.com/google.protobuf.StringValue
value: my-config
# root_id MUST match registerRootContext() 2nd param
root_id: add_header
vm_config:
code:
local:
filename: /var/local/lib/wasm-filters/optimized.wasm
runtime: envoy.wasm.runtime.v8
vm_id: my-example
workloadSelector:
labels:
app: ui
version: base
Beside that, I used wasme
for filter scaffolding:
wasme init ./new-filter
Here’s the generated code, in assembly script:
export * from "@solo-io/proxy-runtime/proxy";
import { RootContext, Context, RootContextHelper, ContextHelper, registerRootContext, FilterHeadersStatusValues, stream_context } from "@solo-io/proxy-runtime";
class AddHeaderRoot extends RootContext {
configuration : string;
onConfigure(): bool {
let conf_buffer = super.getConfiguration();
let result = String.UTF8.decode(conf_buffer);
this.configuration = result;
return true;
}
createContext(): Context {
return ContextHelper.wrap(new AddHeader(this));
}
}
class AddHeader extends Context {
root_context : AddHeaderRoot;
constructor(root_context:AddHeaderRoot){
super();
this.root_context = root_context;
}
onResponseHeaders(a: u32): FilterHeadersStatusValues {
const root_context = this.root_context;
if (root_context.configuration == "") {
stream_context.headers.response.add("hello", "world!");
} else {
stream_context.headers.response.add("hello", root_context.configuration);
}
return FilterHeadersStatusValues.Continue;
}
}
registerRootContext(() => { return RootContextHelper.wrap(new AddHeaderRoot()); }, "add_header");
(What it does is just adding a header)
Building:
npm install && npm run asbuild
Send as a config map:
kubectl create cm -n default example-filter --from-file=build/optimized.wasm
Add these pod annotations to mount this configmap
sidecar.istio.io/userVolume: '[{"name":"wasmfilters-dir","configMap": {"name": "example-filter"}}]'
sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/lib/wasm-filters","name":"wasmfilters-dir"}]'
Then, apply the envoyfilter:
kubectl apply -f ./envoyfilter.yml -n default
And finally, curl
ing the service to check that the header is added (it is).
# curl -L -v http://ui.default:8080
[...]
< content-type: text/html;charset=UTF-8
< x-envoy-upstream-service-time: 58
< hello: my-config
* Server envoy is not blacklisted
< server: envoy
[...]