mirror of https://github.com/linkerd/linkerd2.git
73 lines
1.7 KiB
Go
73 lines
1.7 KiB
Go
package profiles
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"regexp"
|
|
|
|
"github.com/emicklei/proto"
|
|
sp "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
// RenderProto reads a protobuf definition file and renders the corresponding
|
|
// ServiceProfile to a buffer, given a namespace, service, and control plane
|
|
// namespace.
|
|
func RenderProto(fileName, namespace, name, clusterDomain string, w io.Writer) error {
|
|
input, err := readFile(fileName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
parser := proto.NewParser(input)
|
|
|
|
profile, err := protoToServiceProfile(parser, namespace, name, clusterDomain)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return writeProfile(*profile, w)
|
|
}
|
|
|
|
func protoToServiceProfile(parser *proto.Parser, namespace, name, clusterDomain string) (*sp.ServiceProfile, error) {
|
|
definition, err := parser.Parse()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
routes := make([]*sp.RouteSpec, 0)
|
|
pkg := ""
|
|
|
|
handle := func(visitee proto.Visitee) {
|
|
switch typed := visitee.(type) {
|
|
case *proto.Package:
|
|
pkg = typed.Name
|
|
case *proto.RPC:
|
|
if service, ok := typed.Parent.(*proto.Service); ok {
|
|
route := &sp.RouteSpec{
|
|
Name: typed.Name,
|
|
Condition: &sp.RequestMatch{
|
|
Method: http.MethodPost,
|
|
PathRegex: regexp.QuoteMeta(fmt.Sprintf("/%s.%s/%s", pkg, service.Name, typed.Name)),
|
|
},
|
|
}
|
|
routes = append(routes, route)
|
|
}
|
|
}
|
|
}
|
|
|
|
proto.Walk(definition, handle)
|
|
|
|
return &sp.ServiceProfile{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: fmt.Sprintf("%s.%s.svc.%s", name, namespace, clusterDomain),
|
|
Namespace: namespace,
|
|
},
|
|
TypeMeta: serviceProfileMeta,
|
|
Spec: sp.ServiceProfileSpec{
|
|
Routes: routes,
|
|
},
|
|
}, nil
|
|
}
|