Skip to content

Commit

Permalink
Merge pull request openshift#18439 from mfojtik/oc-status
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue.

CLI: add support for deployments in oc status

@smarterclayton this is a long overdue...

current state:
```
$ oc status
In project My Project (myproject) on server https://127.0.0.1:8443

svc/ruby-deploy - 172.30.174.234:8080
  deployment/ruby-deploy deploys istag/ruby-deploy:latest <-
    bc/ruby-deploy source builds https://github.com/openshift/ruby-ex.git on istag/ruby-22-centos7:latest
      build #1 failed 5 hours ago - bbb6701: Merge pull request #18 from durandom/master (Ben Parees <[email protected]>)
    deployment #2 running for 4 hours - 0/1 pods (warning: 53 restarts)
    deployment #1 deployed 5 hours ago
```

TODO:

- [x] Add rollouts similar to deployment configs
- [x] Fix unit tests / Add unit tests
- [x] Deal with HPA
  • Loading branch information
openshift-merge-robot authored Feb 7, 2018
2 parents d7677ca + e0e0368 commit 0427a13
Show file tree
Hide file tree
Showing 22 changed files with 1,025 additions and 237 deletions.
6 changes: 3 additions & 3 deletions pkg/oc/admin/prune/imageprune/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ func (p *pruner) addDaemonSetsToGraph(dss *kapisext.DaemonSetList) []error {
ds := &dss.Items[i]
desc := fmt.Sprintf("DaemonSet %s", getName(ds))
glog.V(4).Infof("Examining %s", desc)
dsNode := appsgraph.EnsureDaemonSetNode(p.g, ds)
dsNode := kubegraph.EnsureDaemonSetNode(p.g, ds)
errs = append(errs, p.addPodSpecToGraph(getRef(ds), &ds.Spec.Template.Spec, dsNode)...)
}

Expand All @@ -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 Expand Up @@ -615,7 +615,7 @@ func (p *pruner) addReplicaSetsToGraph(rss *kapisext.ReplicaSetList) []error {
rs := &rss.Items[i]
ref := getRef(rs)
glog.V(4).Infof("Examining %s", getKindName(ref))
rsNode := appsgraph.EnsureReplicaSetNode(p.g, rs)
rsNode := kubegraph.EnsureReplicaSetNode(p.g, rs)
errs = append(errs, p.addPodSpecToGraph(ref, &rs.Spec.Template.Spec, rsNode)...)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/oc/cli/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (o *StatusOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, baseC
canRequestProjects, _ := loginutil.CanRequestProjects(config, o.namespace)

o.describer = &describe.ProjectStatusDescriber{
K: kclientset,
KubeClient: kclientset,
ProjectClient: projectClient.Project(),
BuildClient: buildClient.Build(),
ImageClient: imageClient.Image(),
Expand Down
6 changes: 3 additions & 3 deletions pkg/oc/cli/describe/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,12 +473,12 @@ func (d *LatestDeploymentsDescriber) Describe(namespace, name string) (string, e
for i := range deployments {
kubegraph.EnsureReplicationControllerNode(g, &deployments[i])
}
appsedges.AddTriggerEdges(g, dcNode)
appsedges.AddDeploymentEdges(g, dcNode)
appsedges.AddTriggerDeploymentConfigsEdges(g, dcNode)
appsedges.AddDeploymentConfigsDeploymentEdges(g, dcNode)
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
230 changes: 199 additions & 31 deletions pkg/oc/cli/describe/projectstatus.go

Large diffs are not rendered by default.

25 changes: 22 additions & 3 deletions pkg/oc/cli/describe/projectstatus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,23 @@ func TestProjectStatus(t *testing.T) {
},
Time: mustParseTime("2015-04-07T04:12:25Z"),
},
"with deployment": {
File: "deployment.yaml",
ErrFn: func(err error) bool { return err == nil },
Extra: []runtime.Object{
&projectapi.Project{
ObjectMeta: metav1.ObjectMeta{Name: "example", Namespace: ""},
},
},
Contains: []string{
"In project example on server https://example.com:8443\n",
"svc/ruby-deploy",
"deployment/ruby-deploy deploys istag/ruby-deploy:latest <-",
"bc/ruby-deploy source builds https://github.com/openshift/ruby-ex.git on istag/ruby-22-centos7:latest",
"not built yet",
},
Time: mustParseTime("2015-04-07T04:12:25Z"),
},
"with stateful sets": {
File: "statefulset.yaml",
Extra: []runtime.Object{
Expand All @@ -339,7 +356,8 @@ func TestProjectStatus(t *testing.T) {
Contains: []string{
"In project example on server https://example.com:8443\n",
"svc/galera (headless):3306",
"statefulset/mysql manages erkules/galera:basic, created less than a second ago - 3 pods",
"statefulset/mysql manages erkules/galera:basic",
"created less than a second ago - 3 pods",
"* pod/mysql-1 has restarted 7 times",
},
Time: mustParseTime("2015-04-07T04:12:25Z"),
Expand Down Expand Up @@ -446,7 +464,7 @@ func TestProjectStatus(t *testing.T) {
routeClient := routefakeclient.NewSimpleClientset(filterByScheme(routeclientscheme.Scheme, objs...)...)

d := ProjectStatusDescriber{
K: kc,
KubeClient: kc,
ProjectClient: projectClient.Project(),
BuildClient: buildClient.Build(),
ImageClient: imageClient.Image(),
Expand All @@ -458,6 +476,7 @@ func TestProjectStatus(t *testing.T) {
LogsCommandName: "oc logs -p",
SecurityPolicyCommandFormat: "policycommand %s %s",
}
t.Logf("describing %q ...", test.File)
out, err := d.Describe("example", "")
if !test.ErrFn(err) {
t.Errorf("%s: unexpected error: %v", k, err)
Expand Down Expand Up @@ -508,7 +527,7 @@ func TestProjectStatusErrors(t *testing.T) {
})

d := ProjectStatusDescriber{
K: kc,
KubeClient: kc,
ProjectClient: projectClient.Project(),
BuildClient: buildClient.Build(),
ImageClient: imageClient.Image(),
Expand Down
6 changes: 3 additions & 3 deletions pkg/oc/graph/appsgraph/analysis/dc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestMissingImageStreamTag(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
buildedges.AddAllInputOutputEdges(g)
appsedges.AddAllTriggerEdges(g)
appsedges.AddAllTriggerDeploymentConfigsEdges(g)
imageedges.AddAllImageStreamRefEdges(g)
imageedges.AddAllImageStreamImageRefEdges(g)

Expand All @@ -36,7 +36,7 @@ func TestMissingImageStream(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
buildedges.AddAllInputOutputEdges(g)
appsedges.AddAllTriggerEdges(g)
appsedges.AddAllTriggerDeploymentConfigsEdges(g)
imageedges.AddAllImageStreamRefEdges(g)
imageedges.AddAllImageStreamImageRefEdges(g)

Expand All @@ -56,7 +56,7 @@ func TestMissingReadinessProbe(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
buildedges.AddAllInputOutputEdges(g)
appsedges.AddAllTriggerEdges(g)
appsedges.AddAllTriggerDeploymentConfigsEdges(g)
imageedges.AddAllImageStreamRefEdges(g)

markers := FindDeploymentConfigReadinessWarnings(g, osgraph.DefaultNamer, "command probe")
Expand Down
2 changes: 1 addition & 1 deletion pkg/oc/graph/appsgraph/edge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestNamespaceEdgeMatching(t *testing.T) {

fn("ns", g)
fn("other", g)
AddAllDeploymentEdges(g)
AddAllDeploymentConfigsDeploymentEdges(g)

if len(g.Edges()) != 4 {
t.Fatal(g)
Expand Down
14 changes: 7 additions & 7 deletions pkg/oc/graph/appsgraph/edges.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const (
VolumeClaimEdgeKind = "VolumeClaim"
)

// AddTriggerEdges creates edges that point to named Docker image repositories for each image used in the deployment.
func AddTriggerEdges(g osgraph.MutableUniqueGraph, node *appsgraph.DeploymentConfigNode) *appsgraph.DeploymentConfigNode {
// AddTriggerDeploymentConfigsEdges creates edges that point to named Docker image repositories for each image used in the deployment.
func AddTriggerDeploymentConfigsEdges(g osgraph.MutableUniqueGraph, node *appsgraph.DeploymentConfigNode) *appsgraph.DeploymentConfigNode {
podTemplate := node.DeploymentConfig.Spec.Template
if podTemplate == nil {
return node
Expand Down Expand Up @@ -60,15 +60,15 @@ func AddTriggerEdges(g osgraph.MutableUniqueGraph, node *appsgraph.DeploymentCon
return node
}

func AddAllTriggerEdges(g osgraph.MutableUniqueGraph) {
func AddAllTriggerDeploymentConfigsEdges(g osgraph.MutableUniqueGraph) {
for _, node := range g.(graph.Graph).Nodes() {
if dcNode, ok := node.(*appsgraph.DeploymentConfigNode); ok {
AddTriggerEdges(g, dcNode)
AddTriggerDeploymentConfigsEdges(g, dcNode)
}
}
}

func AddDeploymentEdges(g osgraph.MutableUniqueGraph, node *appsgraph.DeploymentConfigNode) *appsgraph.DeploymentConfigNode {
func AddDeploymentConfigsDeploymentEdges(g osgraph.MutableUniqueGraph, node *appsgraph.DeploymentConfigNode) *appsgraph.DeploymentConfigNode {
for _, n := range g.(graph.Graph).Nodes() {
if rcNode, ok := n.(*kubegraph.ReplicationControllerNode); ok {
if rcNode.ReplicationController.Namespace != node.DeploymentConfig.Namespace {
Expand All @@ -84,10 +84,10 @@ func AddDeploymentEdges(g osgraph.MutableUniqueGraph, node *appsgraph.Deployment
return node
}

func AddAllDeploymentEdges(g osgraph.MutableUniqueGraph) {
func AddAllDeploymentConfigsDeploymentEdges(g osgraph.MutableUniqueGraph) {
for _, node := range g.(graph.Graph).Nodes() {
if dcNode, ok := node.(*appsgraph.DeploymentConfigNode); ok {
AddDeploymentEdges(g, dcNode)
AddDeploymentConfigsDeploymentEdges(g, dcNode)
}
}
}
Expand Down
83 changes: 0 additions & 83 deletions pkg/oc/graph/appsgraph/nodes/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,11 @@ package nodes
import (
"github.com/gonum/graph"

kapisext "k8s.io/kubernetes/pkg/apis/extensions"

appsapi "github.com/openshift/origin/pkg/apps/apis/apps"
osgraph "github.com/openshift/origin/pkg/oc/graph/genericgraph"
kubegraph "github.com/openshift/origin/pkg/oc/graph/kubegraph/nodes"
)

// EnsureDaemonSetNode adds the provided daemon set to the graph if it does not exist
func EnsureDaemonSetNode(g osgraph.MutableUniqueGraph, ds *kapisext.DaemonSet) *DaemonSetNode {
dsName := DaemonSetNodeName(ds)
dsNode := osgraph.EnsureUnique(
g,
dsName,
func(node osgraph.Node) graph.Node {
return &DaemonSetNode{Node: node, DaemonSet: ds, IsFound: true}
},
).(*DaemonSetNode)

podTemplateSpecNode := kubegraph.EnsurePodTemplateSpecNode(g, &ds.Spec.Template, ds.Namespace, dsName)
g.AddEdge(dsNode, podTemplateSpecNode, osgraph.ContainsEdgeKind)

return dsNode
}

func FindOrCreateSyntheticDaemonSetNode(g osgraph.MutableUniqueGraph, ds *kapisext.DaemonSet) *DaemonSetNode {
return osgraph.EnsureUnique(
g,
DaemonSetNodeName(ds),
func(node osgraph.Node) graph.Node {
return &DaemonSetNode{Node: node, DaemonSet: ds, IsFound: false}
},
).(*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 Expand Up @@ -92,30 +36,3 @@ func FindOrCreateSyntheticDeploymentConfigNode(g osgraph.MutableUniqueGraph, dc
},
).(*DeploymentConfigNode)
}

// EnsureReplicaSetNode adds the provided replica set to the graph if it does not exist
func EnsureReplicaSetNode(g osgraph.MutableUniqueGraph, rs *kapisext.ReplicaSet) *ReplicaSetNode {
rsName := ReplicaSetNodeName(rs)
rsNode := osgraph.EnsureUnique(
g,
rsName,
func(node osgraph.Node) graph.Node {
return &ReplicaSetNode{Node: node, ReplicaSet: rs, IsFound: true}
},
).(*ReplicaSetNode)

podTemplateSpecNode := kubegraph.EnsurePodTemplateSpecNode(g, &rs.Spec.Template, rs.Namespace, rsName)
g.AddEdge(rsNode, podTemplateSpecNode, osgraph.ContainsEdgeKind)

return rsNode
}

func FindOrCreateSyntheticReplicaSetNode(g osgraph.MutableUniqueGraph, rs *kapisext.ReplicaSet) *ReplicaSetNode {
return osgraph.EnsureUnique(
g,
ReplicaSetNodeName(rs),
func(node osgraph.Node) graph.Node {
return &ReplicaSetNode{Node: node, ReplicaSet: rs, IsFound: false}
},
).(*ReplicaSetNode)
}
86 changes: 0 additions & 86 deletions pkg/oc/graph/appsgraph/nodes/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,14 @@ package nodes
import (
"reflect"

kapisext "k8s.io/kubernetes/pkg/apis/extensions"

appsapi "github.com/openshift/origin/pkg/apps/apis/apps"
osgraph "github.com/openshift/origin/pkg/oc/graph/genericgraph"
)

var (
DaemonSetNodeKind = reflect.TypeOf(kapisext.DaemonSet{}).Name()
DeploymentNodeKind = reflect.TypeOf(kapisext.Deployment{}).Name()
DeploymentConfigNodeKind = reflect.TypeOf(appsapi.DeploymentConfig{}).Name()
ReplicaSetNodeKind = reflect.TypeOf(kapisext.ReplicaSet{}).Name()
)

func DaemonSetNodeName(o *kapisext.DaemonSet) osgraph.UniqueName {
return osgraph.GetUniqueRuntimeObjectNodeName(DaemonSetNodeKind, o)
}

type DaemonSetNode struct {
osgraph.Node
DaemonSet *kapisext.DaemonSet

IsFound bool
}

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

func (n DaemonSetNode) Object() interface{} {
return n.DaemonSet
}

func (n DaemonSetNode) String() string {
return string(DaemonSetNodeName(n.DaemonSet))
}

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 All @@ -96,30 +37,3 @@ func (n DeploymentConfigNode) String() string {
func (*DeploymentConfigNode) Kind() string {
return DeploymentConfigNodeKind
}

func ReplicaSetNodeName(o *kapisext.ReplicaSet) osgraph.UniqueName {
return osgraph.GetUniqueRuntimeObjectNodeName(ReplicaSetNodeKind, o)
}

type ReplicaSetNode struct {
osgraph.Node
ReplicaSet *kapisext.ReplicaSet

IsFound bool
}

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

func (n ReplicaSetNode) Object() interface{} {
return n.ReplicaSet
}

func (n ReplicaSetNode) String() string {
return string(ReplicaSetNodeName(n.ReplicaSet))
}

func (*ReplicaSetNode) Kind() string {
return ReplicaSetNodeKind
}
Loading

0 comments on commit 0427a13

Please sign in to comment.