Skip to content

Commit

Permalink
Fix for Expose DaemonSet transformer state linkerd#2149. Linkerd's cu…
Browse files Browse the repository at this point in the history
…rrent view of each DaemonSet namer will be exposed to :9990/namer_state/io.l5d.k8s.daemonset/namespace/port/service , where namespace/port/service are the required config for the DaemonSet transformer. State is exposed for both namer and interpreter transformers. Multiple stacked transformers are supported, so, if a namer/interpreter has multiple transformers defined, state will be exposed for all of them.

Signed-off-by: dst4096 <[email protected]>
  • Loading branch information
dtacalau committed Oct 16, 2019
1 parent 2097828 commit 991a2dc
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ case class DaemonSetTransformerConfig(
override def mk(params: Params): NameTreeTransformer = {
val client = mkClient(params).configured(param.Label("client"))
def mkNs(ns: String) = Api(client.newService(dst)).withNamespace(ns)
val namer = new MultiNsNamer(Path.empty, None, mkNs)

val namer = new MultiNsNamer(prefix, None, mkNs)

val daemonSet = namer.bind(NameTree.Leaf(Path.Utf8(namespace, port, service)))
if (hostNetwork.getOrElse(false))
new MetadataGatewayTransformer(prefix, daemonSet, Metadata.nodeName)
new MetadataGatewayTransformer(prefix, daemonSet, Metadata.nodeName, namer.adminHandlers)
else
new SubnetGatewayTransformer(prefix, daemonSet, Netmask("255.255.255.0"))
new SubnetGatewayTransformer(prefix, daemonSet, Netmask("255.255.255.0"), namer.adminHandlers)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package io.buoyant.transformer

import com.twitter.finagle.Name.Bound
import com.twitter.finagle._
import com.twitter.finagle.naming.NameInterpreter
import com.twitter.util.{Activity, Future, Var}
import io.buoyant.admin.Admin
import io.buoyant.namer.{DelegateTree, DelegatingNameTreeTransformer, RichActivity}

/**
Expand All @@ -12,23 +14,29 @@ import io.buoyant.namer.{DelegateTree, DelegatingNameTreeTransformer, RichActivi
class SubnetGatewayTransformer(
prefix: Path,
gatewayTree: Activity[NameTree[Bound]],
netmask: Netmask
) extends GatewayTransformer(prefix, gatewayTree, netmask.local)
netmask: Netmask,
handlers: Seq[Admin.Handler] = Seq.empty
) extends GatewayTransformer(prefix, gatewayTree, netmask.local, handlers)

class MetadataGatewayTransformer(
prefix: Path,
gatewayTree: Activity[NameTree[Bound]],
metadataField: String
metadataField: String,
handlers: Seq[Admin.Handler] = Seq.empty
) extends GatewayTransformer(prefix, gatewayTree, {
case (Address.Inet(_, a), Address.Inet(_, b)) => a.get(metadataField) == b.get(metadataField)
case _ => true
})
},
handlers)

class GatewayTransformer(
prefix: Path,
gatewayTree: Activity[NameTree[Bound]],
gatewayPredicate: (Address, Address) => Boolean
) extends DelegatingNameTreeTransformer {
gatewayPredicate: (Address, Address) => Boolean,
handlers: Seq[Admin.Handler] = Seq.empty
) extends DelegatingNameTreeTransformer with Admin.WithHandlers {

override def adminHandlers: Seq[Admin.Handler] = handlers

override protected def transformDelegate(tree: DelegateTree[Bound]): Future[DelegateTree[Bound]] =
gatewayTree.toFuture.map { gateways =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.twitter.server.handler.ResourceHandler
import io.buoyant.admin.Admin.{Handler, NavItem}
import io.buoyant.admin.names.{BoundNamesHandler, DelegateApiHandler, DelegateHandler}
import io.buoyant.admin.{Admin, ConfigHandler, StaticFilter, _}
import io.buoyant.namer.EnumeratingNamer
import io.buoyant.namer.{EnumeratingNamer, WithNameTreeTransformer}
import io.buoyant.router.{Http, RoutingFactory}

object LinkerdAdmin {
Expand Down Expand Up @@ -83,6 +83,22 @@ object LinkerdAdmin {
}
}

def extractTransformersNamerHandlers(namers: Seq[Namer]): Seq[Admin.Handler] = {
namers.flatMap(namer =>
namer match {
case withNameTreeTransformer: WithNameTreeTransformer =>
withNameTreeTransformer.transformers.toSeq.flatMap(transformer =>
transformer match {
case withHandlers: Admin.WithHandlers =>
withHandlers.adminHandlers
case _ =>
Seq()
})
case _ =>
Seq()
})
}

def extractInterpreterHandlers(routers: Seq[Router]): Seq[Admin.Handler] = {
routers.flatMap { router =>
router.interpreter match {
Expand All @@ -96,6 +112,21 @@ object LinkerdAdmin {
}
}

def extractInterpreterTransformerHandlers(routers: Seq[Router]): Seq[Admin.Handler] = {
routers.flatMap(router =>
router.interpreter match {
case withNameTreeTransformer: WithNameTreeTransformer =>
withNameTreeTransformer.transformers.toSeq.flatMap(transformer =>
transformer match {
case withHandlers: Admin.WithHandlers => withHandlers.adminHandlers
case _ =>
Seq()
})
case _ =>
Seq()
})
}

def apply(lc: Linker.LinkerConfig, linker: Linker): Seq[Handler] = {
val navItems = Seq(
NavItem("dtab", "delegator"),
Expand All @@ -119,7 +150,9 @@ object LinkerdAdmin {
linker.namers.map(_._2) ++
linker.routers ++
linker.telemeters
) ++ extractInterpreterHandlers(linker.routers))
) ++ extractTransformersNamerHandlers(linker.namers.map(_._2))
++ extractInterpreterHandlers(linker.routers)
++ extractInterpreterTransformerHandlers(linker.routers))
.map {
case Handler(url, service, css) =>
val adminFilter = new AdminFilter(adminHandler, css)
Expand Down
4 changes: 3 additions & 1 deletion linkerd/docs/transformer.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ This can be used to redirect traffic to a reverse-proxy that runs as a
daemonset.

This transformer assumes that there is a Kubernetes service for the daemonset
which can be used to find all pods in the daemonset.
which can be used to find all pods in the daemonset. The internal state of each daemonset namer can be viewed at the
admin endpoint: `/namer_state/io.l5d.k8s.daemonset/$namespace/$port/$service.json`, where $namespace/$port/$service are the required key configs for the DaemonSetTransformer.


Key | Default Value | Description
--- | ------------- | -----------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import com.twitter.finagle.naming.NameInterpreter
import com.twitter.finagle._
import com.twitter.util.{Activity, Future}
import io.buoyant.admin.Admin
import io.buoyant.admin.Admin.Handler

/**
* A NameTreeTransformer performs some kind of transformation on bound
* NameTrees. These transformers are generally applied to the output of a
* NameInterpreter to do post-processing.
*/

trait WithNameTreeTransformer {
def transformers: Seq[NameTreeTransformer]
}

trait NameTreeTransformer {

protected def transform(tree: NameTree[Name.Bound]): Activity[NameTree[Name.Bound]]
Expand All @@ -19,17 +25,24 @@ trait NameTreeTransformer {
* Create a new NameInterpreter by applying this transformer to the output of
* an existing one.
*/
def wrap(underlying: NameInterpreter): NameInterpreter = new NameInterpreter with Admin.WithHandlers {
def wrap(underlying: NameInterpreter): NameInterpreter = new NameInterpreter with Admin.WithHandlers with WithNameTreeTransformer {
override def bind(dtab: Dtab, path: Path): Activity[NameTree[Bound]] =
underlying.bind(dtab, path).flatMap(transform)

override def adminHandlers: Seq[Admin.Handler] = underlying match {
case withHandlers: Admin.WithHandlers => withHandlers.adminHandlers
case _ => Nil
}

override def transformers: Seq[NameTreeTransformer] = underlying match {
case withNameTreeTransformer: WithNameTreeTransformer => withNameTreeTransformer.transformers ++ Seq(getSelf())
case _ => Seq(getSelf())
}
}

def wrap(underlying: Namer): Namer = new Namer with Admin.WithHandlers {
def getSelf(): NameTreeTransformer = this

def wrap(underlying: Namer): Namer = new Namer with Admin.WithHandlers with WithNameTreeTransformer {
private[this] def isBound(tree: NameTree[Name]): Boolean = {
tree match {
case NameTree.Neg | NameTree.Empty | NameTree.Fail => true
Expand All @@ -49,6 +62,11 @@ trait NameTreeTransformer {
}
}

override def transformers: Seq[NameTreeTransformer] = underlying match {
case withNameTreeTransformer: WithNameTreeTransformer => withNameTreeTransformer.transformers ++ Seq(getSelf())
case _ => Seq(getSelf())
}

override def adminHandlers: Seq[Admin.Handler] = underlying match {
case withHandlers: Admin.WithHandlers => withHandlers.adminHandlers
case _ => Nil
Expand All @@ -66,7 +84,7 @@ trait DelegatingNameTreeTransformer extends NameTreeTransformer {
protected def transformDelegate(tree: DelegateTree[Name.Bound]): Future[DelegateTree[Name.Bound]]

/** Like wrap, but preserving the ability of the NameInterpreter to delegate */
def delegatingWrap(underlying: NameInterpreter with Delegator): NameInterpreter with Delegator = new NameInterpreter with Delegator with Admin.WithHandlers {
def delegatingWrap(underlying: NameInterpreter with Delegator): NameInterpreter with Delegator = new NameInterpreter with Delegator with Admin.WithHandlers with WithNameTreeTransformer {
override def bind(dtab: Dtab, path: Path): Activity[NameTree[Bound]] =
underlying.bind(dtab, path).flatMap(transform)

Expand All @@ -82,6 +100,11 @@ trait DelegatingNameTreeTransformer extends NameTreeTransformer {
case withHandlers: Admin.WithHandlers => withHandlers.adminHandlers
case _ => Nil
}

override def transformers: Seq[NameTreeTransformer] = underlying match {
case withNameTreeTransformer: WithNameTreeTransformer => withNameTreeTransformer.transformers ++ Seq(getSelf())
case _ => Seq(getSelf())
}
}
}

Expand Down

0 comments on commit 991a2dc

Please sign in to comment.