Merge pull request #2452 from weaveworks/mike/docker-swarm/service-ns-selector

Add docker swarm Stack selector ala k8s namespace selector
This commit is contained in:
Alfonso Acosta
2017-04-25 15:57:15 +02:00
committed by GitHub
4 changed files with 54 additions and 15 deletions

View File

@@ -12,6 +12,7 @@ import (
"github.com/gorilla/mux"
"golang.org/x/net/context"
"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/probe/kubernetes"
"github.com/weaveworks/scope/render"
"github.com/weaveworks/scope/report"
@@ -48,12 +49,12 @@ var (
}
)
// kubernetesFilters generates the current kubernetes filters based on the
// available k8s topologies.
func kubernetesFilters(namespaces ...string) APITopologyOptionGroup {
options := APITopologyOptionGroup{ID: "namespace", Default: "", SelectType: "union", NoneLabel: "All Namespaces"}
// namespaceFilters generates a namespace selector option group based on the given namespaces
func namespaceFilters(namespaces []string, defaultNamespace, noneLabel string) APITopologyOptionGroup {
options := APITopologyOptionGroup{ID: "namespace", Default: "", SelectType: "union", NoneLabel: noneLabel}
for _, namespace := range namespaces {
if namespace == "default" {
if defaultNamespace != "" && namespace == defaultNamespace {
// We only set the default namespace as options.Default if it is present, otherwise default to All
options.Default = namespace
}
options.Options = append(options.Options, APITopologyOption{
@@ -64,8 +65,40 @@ func kubernetesFilters(namespaces ...string) APITopologyOptionGroup {
}
// updateFilters updates the available filters based on the current report.
// Currently only kubernetes changes.
func updateFilters(rpt report.Report, topologies []APITopologyDesc) []APITopologyDesc {
topologies = updateKubeFilters(rpt, topologies)
topologies = updateSwarmFilters(rpt, topologies)
return topologies
}
func updateSwarmFilters(rpt report.Report, topologies []APITopologyDesc) []APITopologyDesc {
namespaces := map[string]struct{}{}
for _, n := range rpt.SwarmService.Nodes {
if namespace, ok := n.Latest.Lookup(docker.StackNamespace); ok {
namespaces[namespace] = struct{}{}
}
}
if len(namespaces) == 0 {
// We only want to apply filters when we have swarm-related nodes,
// so if we don't then return early
return topologies
}
ns := []string{}
for namespace := range namespaces {
ns = append(ns, namespace)
}
topologies = append([]APITopologyDesc{}, topologies...) // Make a copy so we can make changes safely
for i, t := range topologies {
if t.id == containersID || t.id == containersByImageID || t.id == containersByHostnameID || t.id == swarmServicesID {
topologies[i] = mergeTopologyFilters(t, []APITopologyOptionGroup{
namespaceFilters(ns, docker.DefaultNamespace, "All Stacks"),
})
}
}
return topologies
}
func updateKubeFilters(rpt report.Report, topologies []APITopologyDesc) []APITopologyDesc {
namespaces := map[string]struct{}{}
for _, t := range []report.Topology{rpt.Pod, rpt.Service, rpt.Deployment, rpt.ReplicaSet} {
for _, n := range t.Nodes {
@@ -91,7 +124,7 @@ func updateFilters(rpt report.Report, topologies []APITopologyDesc) []APITopolog
for i, t := range topologies {
if t.id == containersID || t.id == containersByImageID || t.id == containersByHostnameID || t.id == podsID || t.id == servicesID || t.id == deploymentsID || t.id == replicaSetsID {
topologies[i] = mergeTopologyFilters(t, []APITopologyOptionGroup{
kubernetesFilters(ns...),
namespaceFilters(ns, "default", "All Namespaces"),
})
}
}

View File

@@ -23,6 +23,7 @@ const (
ImageTableID = "image_table"
ServiceName = "service_name"
StackNamespace = "stack_namespace"
DefaultNamespace = "No Stack"
)
// Exposed for testing

View File

@@ -59,12 +59,12 @@ func (t *Tagger) Tag(r report.Report) (report.Report, error) {
}
stackNamespace, ok := container.Latest.Lookup(LabelPrefix + "com.docker.stack.namespace")
if !ok {
continue
}
prefix := stackNamespace + "_"
if strings.HasPrefix(serviceName, prefix) {
serviceName = serviceName[len(prefix):]
stackNamespace = DefaultNamespace
} else {
prefix := stackNamespace + "_"
if strings.HasPrefix(serviceName, prefix) {
serviceName = serviceName[len(prefix):]
}
}
nodeID := report.MakeSwarmServiceNodeID(serviceID)

View File

@@ -11,7 +11,8 @@ import (
)
const (
k8sNamespaceLabel = "io.kubernetes.pod.namespace"
k8sNamespaceLabel = "io.kubernetes.pod.namespace"
swarmNamespaceLabel = "com.docker.stack.namespace"
)
// PreciousNodeRenderer ensures a node is never filtered out by decorators
@@ -330,7 +331,7 @@ func IsPseudoTopology(n report.Node) bool {
// IsNamespace checks if the node is a pod/service in the specified namespace
func IsNamespace(namespace string) FilterFunc {
return func(n report.Node) bool {
tryKeys := []string{kubernetes.Namespace, docker.LabelPrefix + k8sNamespaceLabel}
tryKeys := []string{kubernetes.Namespace, docker.LabelPrefix + k8sNamespaceLabel, docker.StackNamespace, docker.LabelPrefix + swarmNamespaceLabel}
gotNamespace := ""
for _, key := range tryKeys {
if value, ok := n.Latest.Lookup(key); ok {
@@ -338,6 +339,10 @@ func IsNamespace(namespace string) FilterFunc {
break
}
}
// Special case for docker
if namespace == docker.DefaultNamespace && gotNamespace == "" {
return true
}
return namespace == gotNamespace
}
}