mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 22:17:14 +00:00
kubectl: refactor rollout history to be more configurable
ChangeCauseAnnotation is hardcoded in PrintRolloutHistory and it needs to be overriden since other resources that may need to be added in `kubectl rollout history` may not use it. Instead of adding one more method in the factory, refactor the existing HistoryViewer interface to accomodate the change.
This commit is contained in:
parent
39bfa168cd
commit
ad33c5c087
@ -70,7 +70,7 @@ func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []st
|
|||||||
if len(args) == 0 && len(options.Filenames) == 0 {
|
if len(args) == 0 && len(options.Filenames) == 0 {
|
||||||
return cmdutil.UsageError(cmd, "Required resource not specified.")
|
return cmdutil.UsageError(cmd, "Required resource not specified.")
|
||||||
}
|
}
|
||||||
revisionDetail := cmdutil.GetFlagInt64(cmd, "revision")
|
revision := cmdutil.GetFlagInt64(cmd, "revision")
|
||||||
|
|
||||||
mapper, typer := f.Object(false)
|
mapper, typer := f.Object(false)
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []st
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.Visit(func(info *resource.Info, err error) error {
|
return r.Visit(func(info *resource.Info, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -101,28 +101,17 @@ func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
historyInfo, err := historyViewer.History(info.Namespace, info.Name)
|
historyInfo, err := historyViewer.ViewHistory(info.Namespace, info.Name, revision)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if revisionDetail > 0 {
|
header := fmt.Sprintf("%s %q", mapping.Resource, info.Name)
|
||||||
// Print details of a specific revision
|
if revision > 0 {
|
||||||
template, ok := historyInfo.RevisionToTemplate[revisionDetail]
|
header = fmt.Sprintf("%s with revision #%d", header, revision)
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("unable to find revision %d of %s %q", revisionDetail, mapping.Resource, info.Name)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(out, "%s %q revision %d\n", mapping.Resource, info.Name, revisionDetail)
|
|
||||||
kubectl.DescribePodTemplate(template, out)
|
|
||||||
} else {
|
|
||||||
// Print all revisions
|
|
||||||
formattedOutput, printErr := kubectl.PrintRolloutHistory(historyInfo, mapping.Resource, info.Name)
|
|
||||||
if printErr != nil {
|
|
||||||
return printErr
|
|
||||||
}
|
|
||||||
fmt.Fprintf(out, "%s\n", formattedOutput)
|
|
||||||
}
|
}
|
||||||
|
fmt.Fprintf(out, "%s\n", header)
|
||||||
|
fmt.Fprintf(out, "%s\n", historyInfo)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package kubectl
|
package kubectl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -34,9 +35,9 @@ const (
|
|||||||
ChangeCauseAnnotation = "kubernetes.io/change-cause"
|
ChangeCauseAnnotation = "kubernetes.io/change-cause"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HistoryViewer provides an interface for resources that can be rolled back.
|
// HistoryViewer provides an interface for resources have historical information.
|
||||||
type HistoryViewer interface {
|
type HistoryViewer interface {
|
||||||
History(namespace, name string) (HistoryInfo, error)
|
ViewHistory(namespace, name string, revision int64) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HistoryViewerFor(kind unversioned.GroupKind, c clientset.Interface) (HistoryViewer, error) {
|
func HistoryViewerFor(kind unversioned.GroupKind, c clientset.Interface) (HistoryViewer, error) {
|
||||||
@ -47,68 +48,68 @@ func HistoryViewerFor(kind unversioned.GroupKind, c clientset.Interface) (Histor
|
|||||||
return nil, fmt.Errorf("no history viewer has been implemented for %q", kind)
|
return nil, fmt.Errorf("no history viewer has been implemented for %q", kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HistoryInfo stores the mapping from revision to podTemplate;
|
|
||||||
// note that change-cause annotation should be copied to podTemplate
|
|
||||||
type HistoryInfo struct {
|
|
||||||
RevisionToTemplate map[int64]*api.PodTemplateSpec
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeploymentHistoryViewer struct {
|
type DeploymentHistoryViewer struct {
|
||||||
c clientset.Interface
|
c clientset.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// History returns a revision-to-replicaset map as the revision history of a deployment
|
// ViewHistory returns a revision-to-replicaset map as the revision history of a deployment
|
||||||
func (h *DeploymentHistoryViewer) History(namespace, name string) (HistoryInfo, error) {
|
func (h *DeploymentHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) {
|
||||||
historyInfo := HistoryInfo{
|
|
||||||
RevisionToTemplate: make(map[int64]*api.PodTemplateSpec),
|
|
||||||
}
|
|
||||||
deployment, err := h.c.Extensions().Deployments(namespace).Get(name)
|
deployment, err := h.c.Extensions().Deployments(namespace).Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return historyInfo, fmt.Errorf("failed to retrieve deployment %s: %v", name, err)
|
return "", fmt.Errorf("failed to retrieve deployment %s: %v", name, err)
|
||||||
}
|
}
|
||||||
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, h.c)
|
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, h.c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return historyInfo, fmt.Errorf("failed to retrieve replica sets from deployment %s: %v", name, err)
|
return "", fmt.Errorf("failed to retrieve replica sets from deployment %s: %v", name, err)
|
||||||
}
|
}
|
||||||
allRSs := allOldRSs
|
allRSs := allOldRSs
|
||||||
if newRS != nil {
|
if newRS != nil {
|
||||||
allRSs = append(allRSs, newRS)
|
allRSs = append(allRSs, newRS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
historyInfo := make(map[int64]*api.PodTemplateSpec)
|
||||||
for _, rs := range allRSs {
|
for _, rs := range allRSs {
|
||||||
v, err := deploymentutil.Revision(rs)
|
v, err := deploymentutil.Revision(rs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
historyInfo.RevisionToTemplate[v] = &rs.Spec.Template
|
historyInfo[v] = &rs.Spec.Template
|
||||||
changeCause := getChangeCause(rs)
|
changeCause := getChangeCause(rs)
|
||||||
if historyInfo.RevisionToTemplate[v].Annotations == nil {
|
if historyInfo[v].Annotations == nil {
|
||||||
historyInfo.RevisionToTemplate[v].Annotations = make(map[string]string)
|
historyInfo[v].Annotations = make(map[string]string)
|
||||||
}
|
}
|
||||||
if len(changeCause) > 0 {
|
if len(changeCause) > 0 {
|
||||||
historyInfo.RevisionToTemplate[v].Annotations[ChangeCauseAnnotation] = changeCause
|
historyInfo[v].Annotations[ChangeCauseAnnotation] = changeCause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return historyInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrintRolloutHistory prints a formatted table of the input revision history of the deployment
|
if len(historyInfo) == 0 {
|
||||||
func PrintRolloutHistory(historyInfo HistoryInfo, resource, name string) (string, error) {
|
return "No rollout history found.", nil
|
||||||
if len(historyInfo.RevisionToTemplate) == 0 {
|
|
||||||
return fmt.Sprintf("No rollout history found in %s %q", resource, name), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if revision > 0 {
|
||||||
|
// Print details of a specific revision
|
||||||
|
template, ok := historyInfo[revision]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("unable to find the specified revision")
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
DescribePodTemplate(template, buf)
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Sort the revisionToChangeCause map by revision
|
// Sort the revisionToChangeCause map by revision
|
||||||
revisions := make([]int64, 0, len(historyInfo.RevisionToTemplate))
|
revisions := make([]int64, 0, len(historyInfo))
|
||||||
for r := range historyInfo.RevisionToTemplate {
|
for r := range historyInfo {
|
||||||
revisions = append(revisions, r)
|
revisions = append(revisions, r)
|
||||||
}
|
}
|
||||||
sliceutil.SortInts64(revisions)
|
sliceutil.SortInts64(revisions)
|
||||||
|
|
||||||
return tabbedString(func(out io.Writer) error {
|
return tabbedString(func(out io.Writer) error {
|
||||||
fmt.Fprintf(out, "%s %q:\n", resource, name)
|
|
||||||
fmt.Fprintf(out, "REVISION\tCHANGE-CAUSE\n")
|
fmt.Fprintf(out, "REVISION\tCHANGE-CAUSE\n")
|
||||||
for _, r := range revisions {
|
for _, r := range revisions {
|
||||||
// Find the change-cause of revision r
|
// Find the change-cause of revision r
|
||||||
changeCause := historyInfo.RevisionToTemplate[r].Annotations[ChangeCauseAnnotation]
|
changeCause := historyInfo[r].Annotations[ChangeCauseAnnotation]
|
||||||
if len(changeCause) == 0 {
|
if len(changeCause) == 0 {
|
||||||
changeCause = "<none>"
|
changeCause = "<none>"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user