-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Out of process Attribute Generating Adapter Developer Walkthrough
This guide should take less than 30 minutes to follow.
Istio 1.1 introduces support for out-of-process attribute generating adapters (occasionally abbreviated as APAs). Attribute generating adapters implement templates of ATTRIBUTE_GENERATOR
variety. Their purpose is to produce additional attributes as a pre-processing step prior to execution of Check()
and Report()
calls. In this guide, we implement a simple mapper
attribute generating adapter, that supplies an extra attribute value using a pre-defined mapping.
- Before you start
- Define a template
- Implement the adapter
- Configure the adapter
- Connect Mixer to the adapter
- Try the new adapter!
- What's next?
You will need a development environment set-up with Go and Kubernetes per Dev Guide.
Download and build a local copy of Istio:
mkdir -p $GOPATH/src/istio.io/ && \
cd $GOPATH/src/istio.io/ && \
git clone https://github.com/istio/istio
cd istio
go build ./...
Install protoc (version 3.5.1 or higher) from https://github.com/google/protobuf/releases and make it available as an executable from $PATH
.
The following template takes a string as input and produces a string as output:
syntax = "proto3";
package mapper;
import "mixer/adapter/model/v1beta1/extensions.proto";
option (istio.mixer.adapter.model.v1beta1.template_variety) = TEMPLATE_VARIETY_ATTRIBUTE_GENERATOR;
message Template {
string key = 1;
}
message OutputTemplate {
string value = 1;
}
Note the template variety declaration; it indicates that the adapter RPC interface should produce an OutputMsg
corresponding to the OutputTemplate
.
Save this file as mixer/adapter/mapper/template.proto
in istio
root directory. Run the following command to generate the code artifacts from the template:
bin/mixer_codegen.sh -t mixer/adapter/mapper/template.proto
After running this command, you should see several new files in mixer/adapter/mapper
directory, including a file called template.yaml
.
Note we generally recommend using pre-defined templates. Istio comes with a kubernetesenv
APA out of the box, which has a template for populating workload metadata from Kubernetes.
Let us write a simple mapper adapter that uses a fixed lookup table. Save the following file as mixer/adapter/mapper/mapper.go
:
package mapper
import context "golang.org/x/net/context"
type MyAdapter struct{}
func (MyAdapter) HandleMapper(_ context.Context, req *HandleMapperRequest) (*OutputMsg, error) {
lookup := map[string]string{
"hello": "world",
}
return &OutputMsg{Value: lookup[req.Instance.Key]}, nil
}
We also need a main function to run the adapter as a standalone process. Save the following file as mixer/adapter/mapper/main/main.go
:
package main
import (
"net"
"google.golang.org/grpc"
"istio.io/istio/mixer/adapter/mapper"
)
func main() {
listener, err := net.Listen("tcp", ":9070")
if err != nil {
panic(err)
}
server := grpc.NewServer()
mapper.RegisterHandleMapperServiceServer(server, mapper.MyAdapter{})
server.Serve(listener)
}
Try running this adapter:
go run mixer/adapter/mapper/main/main.go
If all goes well, the adapter should be waiting to accept requests! If binding to a port fails, feel free to adjust the port number (from 9070).
For Mixer to accept the adapter, we also need to provide a configuration schema for the mapper adapter. We will use the following empty schema:
syntax = "proto3";
package config;
message Params{}
Save this snippet as file mixer/adapter/mapper/config/config.proto
and run the following command to generate the adapter configuration:
bin/mixer_codegen.sh -a mixer/adapter/mapper/config/config.proto -x "-s=false -n myadapter -t mapper"
Note that this command should produce a file called mixer/adapter/mapper/config/myadapter.yaml
. The command above requests that this adapter is called myadapter
, it implements mapper
template, and it is not session-based.
Now that we have all the pieces, we are ready to connect our new adapter to Mixer. Let's start Mixer locally using a Kubernetes cluster for configuration with debug logging:
go run mixer/cmd/mixs/main.go server --configStoreURL=k8s:https://$HOME/.kube/config --log_output_level="api:debug"
In another terminal window, start the adapter:
go run mixer/adapter/mapper/main/main.go
Now that we have both Mixer and the adapter running, load the new template, the adapter definitions, and the handler:
kubectl create namespace istio-system
kubectl apply -f mixer/adapter/mapper/template.yaml
kubectl apply -f mixer/adapter/mapper/config/myadapter.yaml
cat <<EOF | kubectl create -f -
apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
name: h1
namespace: istio-system
spec:
adapter: myadapter
connection:
address: ":9070"
params: {}
EOF
To activate the handler, we need to supply an input instance and the output mapping. First, let us load the attribute declarations:
kubectl apply -f mixer/testdata/config/attributes.yaml
Then define the following input instance:
cat <<EOF | kubectl create -f -
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
name: i1
namespace: istio-system
spec:
template: mapper
params:
key: destination.namespace
attribute_bindings:
source.namespace: output.value | "unknown"
EOF
This instance sets the key
field in the mapper
template to the value of destination.namespace
. After myadapter
executes on this instance, it applies the output as the value for source.namespace
attribute.
Finally, let us add an unconditional rule to define an action application for myadapter
:
cat <<EOF | kubectl create -f -
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
name: r1
namespace: istio-system
spec:
actions:
- handler: h1.istio-system
instances: ["i1"]
EOF
We can use mixc
command line tool to validate the new adapter. Run the following command to test myadapter
:
go run mixer/cmd/mixc/main.go report -s destination.namespace="hello"
Take a look at mixc
debug log. You should see the following attribute bag created during pre-processing:
debug api Dispatching Preprocess
debug api Dispatching to main adapters after running preprocessors
debug api Attribute Bag:
destination.namespace : hello
---
source.namespace : world
Congratulations! We successfully implemented a new attribute generating adapter that automatically binds source.namespace
attribute.
Let us try different input attribute values:
go run mixer/cmd/mixc/main.go report -s destination.namespace="hell"
The output of mixs
should be:
Attribute Bag:
destination.namespace : hell
---
source.namespace : unknown
Now let us try to set source.namespace
value in the input:
go run mixer/cmd/mixc/main.go report -s destination.namespace="hello",source.namespace="hello"
The output of mixs
should be:
Attribute Bag:
destination.namespace : hello
source.namespace : hello
This points to the fact that attribute-generating adapter do not override existing values if they are already set.
You can follow the rest of the adapter development guide to set up an integration test, or to package and distribute your custom adapter.
To clean up, delete the directory istio/mixer/adapter/mapper
, and remove the kubernetes resources:
kubectl delete rule/r1 handler/h1 instance/i1 adapter/myadapter template/mapper -n istio-system
Visit istio.io to learn how to use Istio.