View a markdown version of this page

Transform live traffic (Traffic Replayer) - Migration Assistant for Amazon OpenSearch Service

Transform live traffic (Traffic Replayer)

During migrations, some requests may need to be transformed between versions. Traffic Replayer automatically rewrites host and authentication headers. For more complex transformations, specify custom transformation rules in your workflow configuration using the replayerConfig section.

Elasticsearch content-type header compatibility

Newer Elasticsearch clients (version 7.11 and later, including all 8.x versions) use Elasticsearch-specific media types in Content-Type and Accept headers, such as application/vnd.elasticsearch+json;compatible-with=8. Amazon OpenSearch Service and Amazon OpenSearch Serverless NextGen do not support these media types.

If you are migrating traffic from Elasticsearch clients version 7.11 or later, apply a transformation to convert these headers to standard application/json.

Recommended: use requestTransforms

Use the workflow transform pipeline when you want the workflow to mount the transform file and generate the Traffic Replayer transformer configuration.

  1. Create a JavaScript transformation file. You can author it anywhere you run kubectl, such as the Migration Console pod:

    cat > content-type-transformer.js << 'SCRIPT' const NEW_CONTENT_TYPE = "application/json"; const ELASTIC_CONTENT_TYPE = "application/vnd.elasticsearch+json"; function transform(request, context) { let headers = request.get("headers"); if (headers) { let contentType = headers.get("Content-Type"); if (Array.isArray(contentType)) { headers.set("Content-Type", contentType.map(v => v.includes(ELASTIC_CONTENT_TYPE) ? NEW_CONTENT_TYPE : v)); } else if (typeof contentType === "string") { if (contentType.includes(ELASTIC_CONTENT_TYPE)) { headers.set("Content-Type", NEW_CONTENT_TYPE); } } let accept = headers.get("Accept"); if (Array.isArray(accept)) { headers.set("Accept", accept.map(v => v.includes(ELASTIC_CONTENT_TYPE) ? NEW_CONTENT_TYPE : v)); } else if (typeof accept === "string") { if (accept.includes(ELASTIC_CONTENT_TYPE)) { headers.set("Accept", NEW_CONTENT_TYPE); } } } return request; } function main(context) { return (request) => { if (Array.isArray(request)) { return request.flat().map(item => transform(item, context)); } return transform(request, context); }; } (() => main)(); SCRIPT
  2. Create a ConfigMap from the transformation file:

    kubectl create configmap replayer-transforms -n ma \ --from-file=content-type-transformer.js=content-type-transformer.js
  3. Add the transformation to the workflow configuration under the replayer’s replayerConfig. The examples in this section show only the relevant replayer entry; keep the rest of the workflow configuration, including the captured-traffic source referenced by fromCapturedTraffic and the target cluster referenced by toTarget.

    { "traffic": { "replayers": { "replay1": { "fromCapturedTraffic": "capture-proxy", "toTarget": "target", "replayerConfig": { "requestTransforms": [ { "entryPoint": { "javascriptFile": { "configMap": "replayer-transforms", "path": "content-type-transformer.js" } } } ] } } } } }

    The ConfigMap must already exist in the migration namespace, and path is the ConfigMap key that contains the transform file. Keep the replayer’s existing fromCapturedTraffic and toTarget values when you add replayerConfig. For image-backed transforms, use {"image": "example.com/transforms@sha256:…​", "path": "request.js"} instead. For the full workflow transform schema, including inline scripts, Python, named providers, and context values, see Workflow transform pipeline model.

Alternative: use a raw inline transformer configuration

If you are not using the workflow transform pipeline, provide the raw transformer configuration inline through transformerConfig. The workflow passes the value directly to the Traffic Replayer, so no ConfigMap or shared filesystem is required. The Traffic Replayer pod does not read files from the Migration Console filesystem, so use transformerConfigFile only when you mount the file into the replayer container yourself.

Build the configuration from your JavaScript file with jq, which embeds the script as the initializationScript value without manual escaping:

jq -Rs '[{"JsonJSTransformerProvider":{"initializationScript":.,"bindingsObject":"{}"}}]' \ content-type-transformer.js

Use the single-line output as the transformerConfig value:

{ "traffic": { "replayers": { "replay1": { "fromCapturedTraffic": "capture-proxy", "toTarget": "target", "replayerConfig": { "transformerConfig": "[{\"JsonJSTransformerProvider\":{\"initializationScript\":\"...\",\"bindingsObject\":\"{}\"}}]" } } } } }

For configurations that are cumbersome to encode as a single-line JSON string, pipe the same output through base64 -w0 and provide it through transformerConfigEncoded instead.

Replayer transformation configuration fields

Use request transforms when you need to modify a captured request before Traffic Replayer sends it to the target. Use tuple transforms when you need to modify the request/response tuple output that Traffic Replayer records for validation or analysis.

Field Use

requestTransforms

Preferred workflow pipeline for request transforms. Each entry uses either entryPoint for inline or file-backed JavaScript/Python, or transformName for a named transformer provider.

transformerConfig

Inline raw request transformer configuration as a JSON string.

transformerConfigEncoded

Base64-encoded raw request transformer configuration.

transformerConfigFile

[Expert] Path to a raw request transformer configuration file. The file must already be mounted into the Traffic Replayer container by the user; it is not wired through the workflow, and Migration Console files are not mounted into the replayer pod.

tupleTransforms

Preferred workflow pipeline for tuple transforms.

tupleTransformerConfig

Inline raw tuple transformer configuration as a JSON string.

tupleTransformerConfigBase64

Base64-encoded raw tuple transformer configuration.

tupleTransformerConfigFile

[Expert] Path to a raw tuple transformer configuration file that is already mounted into the Traffic Replayer container by the user.

Note

For each pipeline type, use either the workflow pipeline field or the raw configuration fields, not both. For example, do not configure requestTransforms together with transformerConfig, transformerConfigEncoded, or transformerConfigFile.

The raw request transformer configuration is an array of transformer-provider objects. For JavaScript request transforms, use JsonJSTransformerProvider with either initializationScript or initializationScriptFile.

[ { "JsonJSTransformerProvider": { "initializationScriptFile": "/path/to/request-transform.js", "bindingsObject": "{}" } } ]