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 9d6effe
Show file tree
Hide file tree
Showing 12 changed files with 302 additions and 80 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
73 changes: 58 additions & 15 deletions pkg/oc/cli/describe/projectstatus.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func (d *ProjectStatusDescriber) MakeGraph(namespace string) (osgraph.Graph, set
buildedges.AddAllInputOutputEdges(g)
buildedges.AddAllBuildEdges(g)
appsedges.AddAllTriggerEdges(g)
kubeedges.AddAllTriggerEdges(g)
appsedges.AddAllDeploymentEdges(g)
appsedges.AddAllVolumeClaimEdges(g)
imageedges.AddAllImageStreamRefEdges(g)
Expand Down Expand Up @@ -228,7 +229,7 @@ func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error
printLines(out, "", 0, describeServiceInServiceGroup(f, service, exposes...)...)

for _, dcPipeline := range service.DeploymentConfigPipelines {
printLines(out, indent, 1, describeDeploymentInServiceGroup(local, dcPipeline, func(rc *kubegraph.ReplicationControllerNode) int32 {
printLines(out, indent, 1, describeDeploymentConfigInServiceGroup(local, dcPipeline, func(rc *kubegraph.ReplicationControllerNode) int32 {
return graphview.MaxRecentContainerRestartsForRC(g, rc)
})...)
}
Expand All @@ -237,6 +238,10 @@ func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error
printLines(out, indent, 1, describeStatefulSetInServiceGroup(local, node)...)
}

for _, node := range service.Deployments {
printLines(out, indent, 1, describeDeploymentInServiceGroup(local, node)...)
}

rcNode:
for _, rcNode := range service.FulfillingRCs {
for _, coveredDC := range service.FulfillingDCs {
Expand Down Expand Up @@ -267,7 +272,7 @@ func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error

for _, standaloneDC := range standaloneDCs {
fmt.Fprintln(out)
printLines(out, indent, 0, describeDeploymentInServiceGroup(f, standaloneDC, func(rc *kubegraph.ReplicationControllerNode) int32 {
printLines(out, indent, 0, describeDeploymentConfigInServiceGroup(f, standaloneDC, func(rc *kubegraph.ReplicationControllerNode) int32 {
return graphview.MaxRecentContainerRestartsForRC(g, rc)
})...)
}
Expand Down Expand Up @@ -508,6 +513,8 @@ func (f namespacedFormatter) ResourceName(obj interface{}) string {
return namespaceNameWithType("hpa", t.HorizontalPodAutoscaler.Name, t.HorizontalPodAutoscaler.Namespace, f.currentNamespace, f.hideNamespace)
case *kubegraph.StatefulSetNode:
return namespaceNameWithType("statefulset", t.StatefulSet.Name, t.StatefulSet.Namespace, f.currentNamespace, f.hideNamespace)
case *kubegraph.DeploymentNode:
return namespaceNameWithType("deployment", t.Deployment.Name, t.Deployment.Namespace, f.currentNamespace, f.hideNamespace)
case *kubegraph.PersistentVolumeClaimNode:
return namespaceNameWithType("pvc", t.PersistentVolumeClaim.Name, t.PersistentVolumeClaim.Namespace, f.currentNamespace, f.hideNamespace)

Expand Down Expand Up @@ -550,36 +557,67 @@ func describeAllProjectsOnServer(f formatter, server string) string {
return fmt.Sprintf("Showing all projects on server %s\n", server)
}

func describeDeploymentInServiceGroup(f formatter, deploy graphview.DeploymentConfigPipeline, restartFn func(*kubegraph.ReplicationControllerNode) int32) []string {
local := namespacedFormatter{currentNamespace: deploy.Deployment.DeploymentConfig.Namespace}
func describeDeploymentConfigInServiceGroup(f formatter, deploy graphview.DeploymentConfigPipeline, restartFn func(*kubegraph.ReplicationControllerNode) int32) []string {
local := namespacedFormatter{currentNamespace: deploy.DeploymentConfig.DeploymentConfig.Namespace}

includeLastPass := deploy.ActiveDeployment == nil
if len(deploy.Images) == 1 {
format := "%s deploys %s %s"
if deploy.Deployment.DeploymentConfig.Spec.Test {
if deploy.DeploymentConfig.DeploymentConfig.Spec.Test {
format = "%s test deploys %s %s"
}
lines := []string{fmt.Sprintf(format, f.ResourceName(deploy.Deployment), describeImageInPipeline(local, deploy.Images[0], deploy.Deployment.DeploymentConfig.Namespace), describeDeploymentConfigTrigger(deploy.Deployment.DeploymentConfig))}
lines := []string{fmt.Sprintf(format, f.ResourceName(deploy.DeploymentConfig), describeImageInPipeline(local, deploy.Images[0], deploy.DeploymentConfig.DeploymentConfig.Namespace), describeDeploymentConfigTrigger(deploy.DeploymentConfig.DeploymentConfig))}
if len(lines[0]) > 120 && strings.Contains(lines[0], " <- ") {
segments := strings.SplitN(lines[0], " <- ", 2)
lines[0] = segments[0] + " <-"
lines = append(lines, segments[1])
}
lines = append(lines, indentLines(" ", describeAdditionalBuildDetail(deploy.Images[0].Build, deploy.Images[0].LastSuccessfulBuild, deploy.Images[0].LastUnsuccessfulBuild, deploy.Images[0].ActiveBuilds, deploy.Images[0].DestinationResolved, includeLastPass)...)...)
lines = append(lines, describeDeployments(local, deploy.Deployment, deploy.ActiveDeployment, deploy.InactiveDeployments, restartFn, maxDisplayDeployments)...)
lines = append(lines, describeDeploymentConfigDeployments(local, deploy.DeploymentConfig, deploy.ActiveDeployment, deploy.InactiveDeployments, restartFn, maxDisplayDeployments)...)
return lines
}

format := "%s deploys %s"
if deploy.Deployment.DeploymentConfig.Spec.Test {
if deploy.DeploymentConfig.DeploymentConfig.Spec.Test {
format = "%s test deploys %s"
}
lines := []string{fmt.Sprintf(format, f.ResourceName(deploy.Deployment), describeDeploymentConfigTrigger(deploy.Deployment.DeploymentConfig))}
lines := []string{fmt.Sprintf(format, f.ResourceName(deploy.DeploymentConfig), describeDeploymentConfigTrigger(deploy.DeploymentConfig.DeploymentConfig))}
for _, image := range deploy.Images {
lines = append(lines, describeImageInPipeline(local, image, deploy.DeploymentConfig.DeploymentConfig.Namespace))
lines = append(lines, indentLines(" ", describeAdditionalBuildDetail(image.Build, image.LastSuccessfulBuild, image.LastUnsuccessfulBuild, image.ActiveBuilds, image.DestinationResolved, includeLastPass)...)...)
lines = append(lines, describeDeploymentConfigDeployments(local, deploy.DeploymentConfig, deploy.ActiveDeployment, deploy.InactiveDeployments, restartFn, maxDisplayDeployments)...)
}
return lines
}

func describeDeploymentInServiceGroup(f formatter, deploy graphview.Deployment) []string {
local := namespacedFormatter{currentNamespace: deploy.Deployment.Deployment.Namespace}
// TODO: Figure out what this is
includeLastPass := false

if len(deploy.Images) == 1 {
format := "%s deploys %s %s"
lines := []string{fmt.Sprintf(format, f.ResourceName(deploy.Deployment), describeImageInPipeline(local, deploy.Images[0], deploy.Deployment.Deployment.Namespace), "")}
if len(lines[0]) > 120 && strings.Contains(lines[0], " <- ") {
segments := strings.SplitN(lines[0], " <- ", 2)
lines[0] = segments[0] + " <-"
lines = append(lines, segments[1])
}
lines = append(lines, indentLines(" ", describeAdditionalBuildDetail(deploy.Images[0].Build, deploy.Images[0].LastSuccessfulBuild, deploy.Images[0].LastUnsuccessfulBuild, deploy.Images[0].ActiveBuilds, deploy.Images[0].DestinationResolved, includeLastPass)...)...)
// TODO: Add replica sets as deployments
// lines = append(lines, describeDeploymentConfigDeployments(local, deploy.DeploymentConfig, deploy.ActiveDeployment, deploy.InactiveDeployments, restartFn, maxDisplayDeployments)...)
return lines
}

format := "%s deploys %s"
lines := []string{fmt.Sprintf(format, f.ResourceName(deploy.Deployment), "")}
for _, image := range deploy.Images {
lines = append(lines, describeImageInPipeline(local, image, deploy.Deployment.DeploymentConfig.Namespace))
lines = append(lines, describeImageInPipeline(local, image, deploy.Deployment.Deployment.Namespace))
lines = append(lines, indentLines(" ", describeAdditionalBuildDetail(image.Build, image.LastSuccessfulBuild, image.LastUnsuccessfulBuild, image.ActiveBuilds, image.DestinationResolved, includeLastPass)...)...)
lines = append(lines, describeDeployments(local, deploy.Deployment, deploy.ActiveDeployment, deploy.InactiveDeployments, restartFn, maxDisplayDeployments)...)
// TODO: Add replica sets as deployments
// lines = append(lines, describeDeploymentConfigDeployments(local, deploy.DeploymentConfig, deploy.ActiveDeployment, deploy.InactiveDeployments, restartFn, maxDisplayDeployments)...)
}

return lines
}

Expand Down Expand Up @@ -1026,7 +1064,7 @@ func describeSourceInPipeline(source *buildapi.BuildSource) (string, bool) {
return "", false
}

func describeDeployments(f formatter, dcNode *appsgraph.DeploymentConfigNode, activeDeployment *kubegraph.ReplicationControllerNode, inactiveDeployments []*kubegraph.ReplicationControllerNode, restartFn func(*kubegraph.ReplicationControllerNode) int32, count int) []string {
func describeDeploymentConfigDeployments(f formatter, dcNode *appsgraph.DeploymentConfigNode, activeDeployment *kubegraph.ReplicationControllerNode, inactiveDeployments []*kubegraph.ReplicationControllerNode, restartFn func(*kubegraph.ReplicationControllerNode) int32, count int) []string {
if dcNode == nil {
return nil
}
Expand All @@ -1050,7 +1088,7 @@ func describeDeployments(f formatter, dcNode *appsgraph.DeploymentConfigNode, ac
if restartFn != nil {
restartCount = restartFn(deployment)
}
out = append(out, describeDeploymentStatus(deployment.ReplicationController, i == 0, dcNode.DeploymentConfig.Spec.Test, restartCount))
out = append(out, describeDeploymentConfigDeploymentStatus(deployment.ReplicationController, i == 0, dcNode.DeploymentConfig.Spec.Test, restartCount))
switch {
case count == -1:
if appsutil.IsCompleteDeployment(deployment.ReplicationController) {
Expand All @@ -1065,7 +1103,7 @@ func describeDeployments(f formatter, dcNode *appsgraph.DeploymentConfigNode, ac
return out
}

func describeDeploymentStatus(rc *kapi.ReplicationController, first, test bool, restartCount int32) string {
func describeDeploymentConfigDeploymentStatus(rc *kapi.ReplicationController, first, test bool, restartCount int32) string {
timeAt := strings.ToLower(formatRelativeTime(rc.CreationTimestamp.Time))
status := appsutil.DeploymentStatusFor(rc)
version := appsutil.DeploymentVersionFor(rc)
Expand Down Expand Up @@ -1099,6 +1137,11 @@ func describeDeploymentStatus(rc *kapi.ReplicationController, first, test bool,
}
}

func describeDeploymentStatus(d *kapisext.Deployment) string {
timeAt := strings.ToLower(formatRelativeTime(d.CreationTimestamp.Time))
return fmt.Sprintf("created %s ago%s", timeAt, describePodSummaryInline(int32(d.Status.Replicas), int32(d.Status.Replicas), int32(d.Spec.Replicas), false, 0))
}

func describeStatefulSetStatus(p *kapps.StatefulSet) string {
timeAt := strings.ToLower(formatRelativeTime(p.CreationTimestamp.Time))
// TODO: Replace first argument in describePodSummaryInline with ReadyReplicas once that's a thing for pet sets.
Expand Down Expand Up @@ -1402,7 +1445,7 @@ func (l *deploymentLoader) Load() error {

func (l *deploymentLoader) AddToGraph(g osgraph.Graph) error {
for i := range l.items {
appsgraph.EnsureDeploymentNode(g, &l.items[i])
kubegraph.EnsureDeploymentNode(g, &l.items[i])
}

return nil
Expand Down
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)
}
59 changes: 59 additions & 0 deletions pkg/oc/graph/genericgraph/graphview/deployments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package graphview

import (
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

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

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 _, uncastPodNode := range g.PredecessorNodesByEdgeKind(node, kubeedges.ManagedByControllerEdgeKind) {
podNode := uncastPodNode.(*kubegraph.PodNode)
covered.Insert(podNode.ID())
view.OwnedPods = append(view.OwnedPods, podNode)
}

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)
}

return view, covered
}
13 changes: 12 additions & 1 deletion pkg/oc/graph/genericgraph/graphview/service_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ type ServiceGroup struct {

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

// TODO: this has to stop
FulfillingStatefulSets []*kubegraph.StatefulSetNode
FulfillingDeployments []*kubegraph.DeploymentNode
FulfillingDCs []*appsgraph.DeploymentConfigNode
FulfillingRCs []*kubegraph.ReplicationControllerNode
FulfillingPods []*kubegraph.PodNode
Expand Down Expand Up @@ -71,8 +73,10 @@ func NewServiceGroup(g osgraph.Graph, serviceNode *kubegraph.ServiceNode) (Servi
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 @@ -109,6 +113,13 @@ func NewServiceGroup(g osgraph.Graph, serviceNode *kubegraph.ServiceNode) (Servi
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 9d6effe

Please sign in to comment.