forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhistory.go
113 lines (93 loc) · 3.2 KB
/
history.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package deploymentconfigs
import (
"bytes"
"fmt"
"sort"
"text/tabwriter"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/kubernetes/pkg/api/legacyscheme"
kapi "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl"
kinternalprinters "k8s.io/kubernetes/pkg/printers/internalversion"
appsv1 "github.com/openshift/api/apps/v1"
appsutil "github.com/openshift/origin/pkg/apps/util"
)
func NewDeploymentConfigHistoryViewer(kc kubernetes.Interface) kubectl.HistoryViewer {
return &DeploymentConfigHistoryViewer{rn: kc.CoreV1()}
}
// DeploymentConfigHistoryViewer is an implementation of the kubectl HistoryViewer interface
// for deployment configs.
type DeploymentConfigHistoryViewer struct {
rn corev1client.ReplicationControllersGetter
}
var _ kubectl.HistoryViewer = &DeploymentConfigHistoryViewer{}
// ViewHistory returns a description of all the history it can find for a deployment config.
func (h *DeploymentConfigHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) {
opts := metav1.ListOptions{LabelSelector: appsutil.ConfigSelector(name).String()}
deploymentList, err := h.rn.ReplicationControllers(namespace).List(opts)
if err != nil {
return "", err
}
if len(deploymentList.Items) == 0 {
return "No rollout history found.", nil
}
items := deploymentList.Items
history := make([]*v1.ReplicationController, 0, len(items))
for i := range items {
history = append(history, &items[i])
}
// Print details of a specific revision
if revision > 0 {
var desired *v1.PodTemplateSpec
// We could use a binary search here but brute-force is always faster to write
for i := range history {
rc := history[i]
if appsutil.DeploymentVersionFor(rc) == revision {
desired = rc.Spec.Template
break
}
}
if desired == nil {
return "", fmt.Errorf("unable to find the specified revision")
}
buf := bytes.NewBuffer([]byte{})
// TODO: remove this once we have external describers
var internalDesired kapi.PodTemplateSpec
if legacyscheme.Scheme.Convert(desired, &internalDesired, nil); err != nil {
return "", fmt.Errorf("unable to convert pod template to internal pod template: %v", err)
}
kinternalprinters.DescribePodTemplate(&internalDesired, kinternalprinters.NewPrefixWriter(buf))
return buf.String(), nil
}
sort.Sort(appsutil.ByLatestVersionAsc(history))
return tabbedString(func(out *tabwriter.Writer) error {
fmt.Fprintf(out, "REVISION\tSTATUS\tCAUSE\n")
for i := range history {
rc := history[i]
rev := appsutil.DeploymentVersionFor(rc)
status := appsutil.AnnotationFor(rc, appsv1.DeploymentStatusAnnotation)
cause := rc.Annotations[appsv1.DeploymentStatusReasonAnnotation]
if len(cause) == 0 {
cause = "<unknown>"
}
fmt.Fprintf(out, "%d\t%s\t%s\n", rev, status, cause)
}
return nil
})
}
// TODO: Re-use from an utility package
func tabbedString(f func(*tabwriter.Writer) error) (string, error) {
out := new(tabwriter.Writer)
buf := &bytes.Buffer{}
out.Init(buf, 0, 8, 1, '\t', 0)
err := f(out)
if err != nil {
return "", err
}
out.Flush()
str := string(buf.String())
return str, nil
}