Skip to content

Commit

Permalink
wip: add support for deployments in oc status
Browse files Browse the repository at this point in the history
  • Loading branch information
mfojtik committed Feb 5, 2018
1 parent d4061a5 commit 8106914
Show file tree
Hide file tree
Showing 14 changed files with 670 additions and 79 deletions.
2 changes: 1 addition & 1 deletion pkg/oc/admin/prune/imageprune/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ func (p *pruner) addDeploymentsToGraph(dmnts *kapisext.DeploymentList) []error {
d := &dmnts.Items[i]
ref := getRef(d)
glog.V(4).Infof("Examining %s", getKindName(ref))
dNode := appsgraph.EnsureDeploymentNode(p.g, d)
dNode := kubegraph.EnsureDeploymentNode(p.g, d)
errs = append(errs, p.addPodSpecToGraph(ref, &d.Spec.Template.Spec, dNode)...)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/oc/cli/describe/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func (d *LatestDeploymentsDescriber) Describe(namespace, name string) (string, e
activeDeployment, inactiveDeployments := appsedges.RelevantDeployments(g, dcNode)

return tabbedString(func(out *tabwriter.Writer) error {
descriptions := describeDeployments(f, dcNode, activeDeployment, inactiveDeployments, nil, d.count)
descriptions := describeDeploymentConfigDeployments(f, dcNode, activeDeployment, inactiveDeployments, nil, d.count)
for i, description := range descriptions {
descriptions[i] = fmt.Sprintf("%v %v", name, description)
}
Expand Down
168 changes: 154 additions & 14 deletions pkg/oc/cli/describe/projectstatus.go

Large diffs are not rendered by default.

27 changes: 0 additions & 27 deletions pkg/oc/graph/appsgraph/nodes/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,6 @@ func FindOrCreateSyntheticDaemonSetNode(g osgraph.MutableUniqueGraph, ds *kapise
).(*DaemonSetNode)
}

// EnsureDeploymentNode adds the provided upstream deployment to the graph if it does not exist
func EnsureDeploymentNode(g osgraph.MutableUniqueGraph, deployment *kapisext.Deployment) *DeploymentNode {
deploymentName := DeploymentNodeName(deployment)
deploymentNode := osgraph.EnsureUnique(
g,
deploymentName,
func(node osgraph.Node) graph.Node {
return &DeploymentNode{Node: node, Deployment: deployment, IsFound: true}
},
).(*DeploymentNode)

podTemplateSpecNode := kubegraph.EnsurePodTemplateSpecNode(g, &deployment.Spec.Template, deployment.Namespace, deploymentName)
g.AddEdge(deploymentNode, podTemplateSpecNode, osgraph.ContainsEdgeKind)

return deploymentNode
}

func FindOrCreateSyntheticDeploymentNode(g osgraph.MutableUniqueGraph, deployment *kapisext.Deployment) *DeploymentNode {
return osgraph.EnsureUnique(
g,
DeploymentNodeName(deployment),
func(node osgraph.Node) graph.Node {
return &DeploymentNode{Node: node, Deployment: deployment, IsFound: false}
},
).(*DeploymentNode)
}

// EnsureDeploymentConfigNode adds the provided deployment config to the graph if it does not exist
func EnsureDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc *appsapi.DeploymentConfig) *DeploymentConfigNode {
dcName := DeploymentConfigNodeName(dc)
Expand Down
27 changes: 0 additions & 27 deletions pkg/oc/graph/appsgraph/nodes/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,33 +43,6 @@ func (*DaemonSetNode) Kind() string {
return DaemonSetNodeKind
}

func DeploymentNodeName(o *kapisext.Deployment) osgraph.UniqueName {
return osgraph.GetUniqueRuntimeObjectNodeName(DeploymentNodeKind, o)
}

type DeploymentNode struct {
osgraph.Node
Deployment *kapisext.Deployment

IsFound bool
}

func (n DeploymentNode) Found() bool {
return n.IsFound
}

func (n DeploymentNode) Object() interface{} {
return n.Deployment
}

func (n DeploymentNode) String() string {
return string(DeploymentNodeName(n.Deployment))
}

func (*DeploymentNode) Kind() string {
return DeploymentNodeKind
}

func DeploymentConfigNodeName(o *appsapi.DeploymentConfig) osgraph.UniqueName {
return osgraph.GetUniqueRuntimeObjectNodeName(DeploymentConfigNodeKind, o)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/oc/graph/genericgraph/graphview/dc_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

type DeploymentConfigPipeline struct {
Deployment *appsgraph.DeploymentConfigNode
DeploymentConfig *appsgraph.DeploymentConfigNode

ActiveDeployment *kubegraph.ReplicationControllerNode
InactiveDeployments []*kubegraph.ReplicationControllerNode
Expand Down Expand Up @@ -43,7 +43,7 @@ func NewDeploymentConfigPipeline(g osgraph.Graph, dcNode *appsgraph.DeploymentCo
covered.Insert(dcNode.ID())

dcPipeline := DeploymentConfigPipeline{}
dcPipeline.Deployment = dcNode
dcPipeline.DeploymentConfig = dcNode

// for everything that can trigger a deployment, create an image pipeline and add it to the list
for _, istNode := range g.PredecessorNodesByEdgeKind(dcNode, appsedges.TriggersDeploymentEdgeKind) {
Expand Down Expand Up @@ -80,5 +80,5 @@ type SortedDeploymentConfigPipeline []DeploymentConfigPipeline
func (m SortedDeploymentConfigPipeline) Len() int { return len(m) }
func (m SortedDeploymentConfigPipeline) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m SortedDeploymentConfigPipeline) Less(i, j int) bool {
return CompareObjectMeta(&m[i].Deployment.DeploymentConfig.ObjectMeta, &m[j].Deployment.DeploymentConfig.ObjectMeta)
return CompareObjectMeta(&m[i].DeploymentConfig.DeploymentConfig.ObjectMeta, &m[j].DeploymentConfig.DeploymentConfig.ObjectMeta)
}
73 changes: 73 additions & 0 deletions pkg/oc/graph/genericgraph/graphview/deployments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package graphview

import (
appsedges "github.com/openshift/origin/pkg/oc/graph/appsgraph"
osgraph "github.com/openshift/origin/pkg/oc/graph/genericgraph"
kubeedges "github.com/openshift/origin/pkg/oc/graph/kubegraph"
kubegraph "github.com/openshift/origin/pkg/oc/graph/kubegraph/nodes"
)

type Deployment struct {
Deployment *kubegraph.DeploymentNode

ActiveDeployment *kubegraph.ReplicaSetNode
InactiveDeployments []*kubegraph.ReplicaSetNode

Images []ImagePipeline

// TODO: handle conflicting once controller refs are present, not worth it yet
}

// AllDeployments returns all the Deployments that aren't in the excludes set and the set of covered NodeIDs
func AllDeployments(g osgraph.Graph, excludeNodeIDs IntSet) ([]Deployment, IntSet) {
covered := IntSet{}
views := []Deployment{}

for _, uncastNode := range g.NodesByKind(kubegraph.DeploymentNodeKind) {
if excludeNodeIDs.Has(uncastNode.ID()) {
continue
}

view, covers := NewDeployment(g, uncastNode.(*kubegraph.DeploymentNode))
covered.Insert(covers.List()...)
views = append(views, view)
}

return views, covered
}

// NewDeployment returns the Deployment and a set of all the NodeIDs covered by the Deployment
func NewDeployment(g osgraph.Graph, node *kubegraph.DeploymentNode) (Deployment, IntSet) {
covered := IntSet{}
covered.Insert(node.ID())

view := Deployment{}
view.Deployment = node

for _, istNode := range g.PredecessorNodesByEdgeKind(node, kubeedges.TriggersDeploymentEdgeKind) {
imagePipeline, covers := NewImagePipelineFromImageTagLocation(g, istNode, istNode.(ImageTagLocation))
covered.Insert(covers.List()...)
view.Images = append(view.Images, imagePipeline)
}

// for image that we use, create an image pipeline and add it to the list
for _, tagNode := range g.PredecessorNodesByEdgeKind(node, appsedges.UsedInDeploymentEdgeKind) {
imagePipeline, covers := NewImagePipelineFromImageTagLocation(g, tagNode, tagNode.(ImageTagLocation))

covered.Insert(covers.List()...)
view.Images = append(view.Images, imagePipeline)
}

view.ActiveDeployment, view.InactiveDeployments = kubeedges.RelevantDeployments(g, view.Deployment)
for _, rs := range view.InactiveDeployments {
_, covers := NewReplicaSet(g, rs)
covered.Insert(covers.List()...)
}

if view.ActiveDeployment != nil {
_, covers := NewReplicaSet(g, view.ActiveDeployment)
covered.Insert(covers.List()...)
}

return view, covered
}
71 changes: 71 additions & 0 deletions pkg/oc/graph/genericgraph/graphview/rs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package graphview

import (
osgraph "github.com/openshift/origin/pkg/oc/graph/genericgraph"
kubeedges "github.com/openshift/origin/pkg/oc/graph/kubegraph"
"github.com/openshift/origin/pkg/oc/graph/kubegraph/analysis"
kubegraph "github.com/openshift/origin/pkg/oc/graph/kubegraph/nodes"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type ReplicaSet struct {
RS *kubegraph.ReplicaSetNode

OwnedPods []*kubegraph.PodNode
CreatedPods []*kubegraph.PodNode
}

func AllReplicaSets(g osgraph.Graph, excludeNodeIDs IntSet) ([]ReplicaSet, IntSet) {
covered := IntSet{}
rsViews := []ReplicaSet{}

for _, uncastNode := range g.NodesByKind(kubegraph.ReplicaSetNodeKind) {
if excludeNodeIDs.Has(uncastNode.ID()) {
continue
}

rsView, covers := NewReplicaSet(g, uncastNode.(*kubegraph.ReplicaSetNode))
covered.Insert(covers.List()...)
rsViews = append(rsViews, rsView)
}

return rsViews, covered
}

// MaxRecentContainerRestarts returns the maximum container restarts for all pods
func (rs *ReplicaSet) MaxRecentContainerRestarts() int32 {
var maxRestarts int32
for _, pod := range rs.OwnedPods {
for _, status := range pod.Status.ContainerStatuses {
if status.RestartCount > maxRestarts && analysis.ContainerRestartedRecently(status, metav1.Now()) {
maxRestarts = status.RestartCount
}
}
}
return maxRestarts
}

// NewReplicationController returns the ReplicationController and a set of all the NodeIDs covered by the ReplicationController
func NewReplicaSet(g osgraph.Graph, rsNode *kubegraph.ReplicaSetNode) (ReplicaSet, IntSet) {
covered := IntSet{}
covered.Insert(rsNode.ID())

rsView := ReplicaSet{}
rsView.RS = rsNode

for _, uncastPodNode := range g.PredecessorNodesByEdgeKind(rsNode, kubeedges.ManagedByControllerEdgeKind) {
podNode := uncastPodNode.(*kubegraph.PodNode)
covered.Insert(podNode.ID())
rsView.OwnedPods = append(rsView.OwnedPods, podNode)
}

return rsView, covered
}

func MaxRecentContainerRestartsForRS(g osgraph.Graph, rsNode *kubegraph.ReplicaSetNode) int32 {
if rsNode == nil {
return 0
}
rs, _ := NewReplicaSet(g, rsNode)
return rs.MaxRecentContainerRestarts()
}
24 changes: 23 additions & 1 deletion pkg/oc/graph/genericgraph/graphview/service_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ type ServiceGroup struct {

DeploymentConfigPipelines []DeploymentConfigPipeline
ReplicationControllers []ReplicationController
ReplicaSets []ReplicaSet
Deployments []Deployment
StatefulSets []StatefulSet

// TODO: this has to stop
FulfillingStatefulSets []*kubegraph.StatefulSetNode
FulfillingDeployments []*kubegraph.DeploymentNode
FulfillingDCs []*appsgraph.DeploymentConfigNode
FulfillingRCs []*kubegraph.ReplicationControllerNode
FulfillingRSs []*kubegraph.ReplicaSetNode
FulfillingPods []*kubegraph.PodNode

ExposingRoutes []*routegraph.RouteNode
Expand Down Expand Up @@ -67,12 +71,16 @@ func NewServiceGroup(g osgraph.Graph, serviceNode *kubegraph.ServiceNode) (Servi
service.FulfillingDCs = append(service.FulfillingDCs, castContainer)
case *kubegraph.ReplicationControllerNode:
service.FulfillingRCs = append(service.FulfillingRCs, castContainer)
case *kubegraph.ReplicaSetNode:
service.FulfillingRSs = append(service.FulfillingRSs, castContainer)
case *kubegraph.PodNode:
service.FulfillingPods = append(service.FulfillingPods, castContainer)
case *kubegraph.StatefulSetNode:
service.FulfillingStatefulSets = append(service.FulfillingStatefulSets, castContainer)
case *kubegraph.DeploymentNode:
service.FulfillingDeployments = append(service.FulfillingDeployments, castContainer)
default:
utilruntime.HandleError(fmt.Errorf("unrecognized container: %v", castContainer))
utilruntime.HandleError(fmt.Errorf("unrecognized container: %v (%T)", castContainer, castContainer))
}
}

Expand Down Expand Up @@ -102,13 +110,27 @@ func NewServiceGroup(g osgraph.Graph, serviceNode *kubegraph.ServiceNode) (Servi
service.ReplicationControllers = append(service.ReplicationControllers, rcView)
}

for _, fulfillingRS := range service.FulfillingRSs {
rsView, rsCovers := NewReplicaSet(g, fulfillingRS)

covered.Insert(rsCovers.List()...)
service.ReplicaSets = append(service.ReplicaSets, rsView)
}

for _, fulfillingStatefulSet := range service.FulfillingStatefulSets {
view, covers := NewStatefulSet(g, fulfillingStatefulSet)

covered.Insert(covers.List()...)
service.StatefulSets = append(service.StatefulSets, view)
}

for _, fulfillingDeployment := range service.FulfillingDeployments {
view, covers := NewDeployment(g, fulfillingDeployment)

covered.Insert(covers.List()...)
service.Deployments = append(service.Deployments, view)
}

for _, fulfillingPod := range service.FulfillingPods {
_, podCovers := NewPod(g, fulfillingPod)
covered.Insert(podCovers.List()...)
Expand Down
4 changes: 2 additions & 2 deletions pkg/oc/graph/genericgraph/graphview/veneering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ func TestGraph(t *testing.T) {
}

for _, bareDCPipeline := range bareDCPipelines {
t.Logf("from %s", bareDCPipeline.Deployment.DeploymentConfig.Name)
t.Logf("from %s", bareDCPipeline.DeploymentConfig.DeploymentConfig.Name)
for _, path := range bareDCPipeline.Images {
t.Logf(" %v", path)
}
Expand All @@ -413,7 +413,7 @@ func TestGraph(t *testing.T) {
indent := " "

for _, deployment := range serviceGroup.DeploymentConfigPipelines {
t.Logf("%sdeployment %s", indent, deployment.Deployment.DeploymentConfig.Name)
t.Logf("%sdeployment %s", indent, deployment.DeploymentConfig.DeploymentConfig.Name)
for _, image := range deployment.Images {
t.Logf("%s image %s", indent, image.Image.ImageSpec())
if image.Build != nil {
Expand Down
Loading

0 comments on commit 8106914

Please sign in to comment.