Skip to content

Commit

Permalink
The probe reports namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
Roberto Bruggemann committed Jan 3, 2018
1 parent 90cbd8d commit ccfcc61
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 0 deletions.
13 changes: 13 additions & 0 deletions probe/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Client interface {
WalkCronJobs(f func(CronJob) error) error
WalkReplicationControllers(f func(ReplicationController) error) error
WalkNodes(f func(*apiv1.Node) error) error
WalkNamespaces(f func(NamespaceResource) error) error

WatchPods(f func(Event, Pod))

Expand All @@ -59,6 +60,7 @@ type client struct {
cronJobStore cache.Store
replicationControllerStore cache.Store
nodeStore cache.Store
namespaceStore cache.Store

podWatchesMutex sync.Mutex
podWatches []func(Event, Pod)
Expand Down Expand Up @@ -158,6 +160,7 @@ func NewClient(config ClientConfig) (Client, error) {
result.serviceStore = result.setupStore(c.CoreV1Client.RESTClient(), "services", &apiv1.Service{}, nil)
result.replicationControllerStore = result.setupStore(c.CoreV1Client.RESTClient(), "replicationcontrollers", &apiv1.ReplicationController{}, nil)
result.nodeStore = result.setupStore(c.CoreV1Client.RESTClient(), "nodes", &apiv1.Node{}, nil)
result.namespaceStore = result.setupStore(c.CoreV1Client.RESTClient(), "namespaces", &apiv1.Namespace{}, nil)

// We list deployments here to check if this version of kubernetes is >= 1.2.
// We would use NegotiateVersion, but Kubernetes 1.1 "supports"
Expand Down Expand Up @@ -326,6 +329,16 @@ func (c *client) WalkNodes(f func(*apiv1.Node) error) error {
return nil
}

func (c *client) WalkNamespaces(f func(NamespaceResource) error) error {
for _, m := range c.namespaceStore.List() {
namespace := m.(*apiv1.Namespace)
if err := f(NewNamespace(namespace)); err != nil {
return err
}
}
return nil
}

func (c *client) GetLogs(namespaceID, podID string) (io.ReadCloser, error) {
req := c.client.CoreV1().Pods(namespaceID).GetLogs(
podID,
Expand Down
33 changes: 33 additions & 0 deletions probe/kubernetes/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,36 @@ func (m meta) MetaNode(id string) report.Node {
Created: m.Created(),
}).AddPrefixPropertyList(LabelPrefix, m.Labels())
}

type namespaceMeta struct {
ObjectMeta metav1.ObjectMeta
}

func (m namespaceMeta) UID() string {
return string(m.ObjectMeta.UID)
}

func (m namespaceMeta) Name() string {
return m.ObjectMeta.Name
}

func (m namespaceMeta) Namespace() string {
return m.ObjectMeta.Namespace
}

func (m namespaceMeta) Created() string {
return m.ObjectMeta.CreationTimestamp.Format(time.RFC3339Nano)
}

func (m namespaceMeta) Labels() map[string]string {
return m.ObjectMeta.Labels
}

// MetaNode gets the node metadata
// For namespaces, ObjectMeta.Namespace is not set
func (m namespaceMeta) MetaNode(id string) report.Node {
return report.MakeNodeWith(id, map[string]string{
Name: m.Name(),
Created: m.Created(),
}).AddPrefixPropertyList(LabelPrefix, m.Labels())
}
28 changes: 28 additions & 0 deletions probe/kubernetes/namespace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package kubernetes

import (
"github.com/weaveworks/scope/report"

apiv1 "k8s.io/client-go/pkg/api/v1"
)

// NamespaceResource represents a Kubernetes namespace
// `Namespace` is already taken in meta.go
type NamespaceResource interface {
Meta
GetNode() report.Node
}

type namespace struct {
ns *apiv1.Namespace
Meta
}

// NewNamespace creates a new Namespace
func NewNamespace(ns *apiv1.Namespace) NamespaceResource {
return &namespace{ns: ns, Meta: namespaceMeta{ns.ObjectMeta}}
}

func (ns *namespace) GetNode() report.Node {
return ns.MetaNode(report.MakeNamespaceNodeID(ns.UID()))
}
14 changes: 14 additions & 0 deletions probe/kubernetes/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,18 @@ func (r *Reporter) Report() (report.Report, error) {
if err != nil {
return result, err
}
namespaceTopology, err := r.namespaceTopology()
if err != nil {
return result, err
}
result.Pod = result.Pod.Merge(podTopology)
result.Service = result.Service.Merge(serviceTopology)
result.Host = result.Host.Merge(hostTopology)
result.DaemonSet = result.DaemonSet.Merge(daemonSetTopology)
result.StatefulSet = result.StatefulSet.Merge(statefulSetTopology)
result.CronJob = result.CronJob.Merge(cronJobTopology)
result.Deployment = result.Deployment.Merge(deploymentTopology)
result.Namespace = result.Namespace.Merge(namespaceTopology)
return result, nil
}

Expand Down Expand Up @@ -500,3 +505,12 @@ func (r *Reporter) podTopology(services []Service, deployments []Deployment, dae
})
return pods, err
}

func (r *Reporter) namespaceTopology() (report.Topology, error) {
result := report.MakeTopology()
err := r.client.WalkNamespaces(func(ns NamespaceResource) error {
result = result.AddNode(ns.GetNode())
return nil
})
return result, err
}
3 changes: 3 additions & 0 deletions probe/kubernetes/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ func (c *mockClient) WalkReplicationControllers(f func(kubernetes.ReplicationCon
func (*mockClient) WalkNodes(f func(*apiv1.Node) error) error {
return nil
}
func (c *mockClient) WalkNamespaces(f func(kubernetes.NamespaceResource) error) error {
return nil
}
func (*mockClient) WatchPods(func(kubernetes.Event, kubernetes.Pod)) {}
func (c *mockClient) GetLogs(namespaceID, podName string) (io.ReadCloser, error) {
r, ok := c.logs[namespaceID+";"+podName]
Expand Down
6 changes: 6 additions & 0 deletions report/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ var (
// ParseCronJobNodeID parses a cronjob node ID
ParseCronJobNodeID = parseSingleComponentID("cronjob")

// MakeNamespaceNodeID produces a namespace node ID from its composite parts.
MakeNamespaceNodeID = makeSingleComponentID("namespace")

// ParseNamespaceNodeID parses a namespace set node ID
ParseNamespaceNodeID = parseSingleComponentID("namespace")

// MakeECSTaskNodeID produces a ECSTask node ID from its composite parts.
MakeECSTaskNodeID = makeSingleComponentID("ecs_task")

Expand Down
11 changes: 11 additions & 0 deletions report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
DaemonSet = "daemon_set"
StatefulSet = "stateful_set"
CronJob = "cron_job"
Namespace = "namespace"
ContainerImage = "container_image"
Host = "host"
Overlay = "overlay"
Expand Down Expand Up @@ -56,6 +57,7 @@ var topologyNames = []string{
DaemonSet,
StatefulSet,
CronJob,
Namespace,
Host,
Overlay,
ECSTask,
Expand Down Expand Up @@ -115,6 +117,11 @@ type Report struct {
// present.
CronJob Topology

// Namespace nodes represent all Kubernetes Namespaces running on hosts running probes.
// Metadata includes things like Namespace id, name, etc. Edges are not
// present.
Namespace Topology

// ContainerImages nodes represent all Docker containers images on
// hosts running probes. Metadata includes things like image id, name etc.
// Edges are not present.
Expand Down Expand Up @@ -217,6 +224,8 @@ func MakeReport() Report {
WithShape(Triangle).
WithLabel("cron job", "cron jobs"),

Namespace: MakeTopology(),

Overlay: MakeTopology().
WithShape(Circle).
WithLabel("peer", "peers"),
Expand Down Expand Up @@ -317,6 +326,8 @@ func (r *Report) topology(name string) *Topology {
return &r.StatefulSet
case CronJob:
return &r.CronJob
case Namespace:
return &r.Namespace
case Host:
return &r.Host
case Overlay:
Expand Down

0 comments on commit ccfcc61

Please sign in to comment.