gets the correct version of kubernetes client for DaemonSet and StatefulSet History and Rollback and updates test-cmd for new versions
This commit is contained in:
@@ -27,18 +27,18 @@ import (
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
clientappsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
|
||||
clientextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
|
||||
clientextv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
|
||||
sliceutil "k8s.io/kubernetes/pkg/kubectl/util/slice"
|
||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||
@@ -53,7 +53,7 @@ type HistoryViewer interface {
|
||||
ViewHistory(namespace, name string, revision int64) (string, error)
|
||||
}
|
||||
|
||||
func HistoryViewerFor(kind schema.GroupKind, c clientset.Interface) (HistoryViewer, error) {
|
||||
func HistoryViewerFor(kind schema.GroupKind, c kubernetes.Interface) (HistoryViewer, error) {
|
||||
switch kind {
|
||||
case extensions.Kind("Deployment"), apps.Kind("Deployment"):
|
||||
return &DeploymentHistoryViewer{c}, nil
|
||||
@@ -66,13 +66,13 @@ func HistoryViewerFor(kind schema.GroupKind, c clientset.Interface) (HistoryView
|
||||
}
|
||||
|
||||
type DeploymentHistoryViewer struct {
|
||||
c clientset.Interface
|
||||
c kubernetes.Interface
|
||||
}
|
||||
|
||||
// ViewHistory returns a revision-to-replicaset map as the revision history of a deployment
|
||||
// TODO: this should be a describer
|
||||
func (h *DeploymentHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) {
|
||||
versionedExtensionsClient := versionedExtensionsClientV1beta1(h.c)
|
||||
versionedExtensionsClient := h.c.ExtensionsV1beta1()
|
||||
deployment, err := versionedExtensionsClient.Deployments(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to retrieve deployment %s: %v", name, err)
|
||||
@@ -148,24 +148,21 @@ func printTemplate(template *v1.PodTemplateSpec) (string, error) {
|
||||
}
|
||||
|
||||
type DaemonSetHistoryViewer struct {
|
||||
c clientset.Interface
|
||||
c kubernetes.Interface
|
||||
}
|
||||
|
||||
// ViewHistory returns a revision-to-history map as the revision history of a deployment
|
||||
// TODO: this should be a describer
|
||||
func (h *DaemonSetHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) {
|
||||
versionedAppsClient := versionedAppsClientV1beta1(h.c)
|
||||
versionedExtensionsClient := versionedExtensionsClientV1beta1(h.c)
|
||||
versionedObj, allHistory, err := controlledHistories(versionedAppsClient, versionedExtensionsClient, namespace, name, "DaemonSet")
|
||||
ds, history, err := daemonSetHistory(h.c.ExtensionsV1beta1(), h.c.AppsV1beta1(), namespace, name)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to find history controlled by DaemonSet %s: %v", name, err)
|
||||
return "", err
|
||||
}
|
||||
historyInfo := make(map[int64]*appsv1beta1.ControllerRevision)
|
||||
for _, history := range allHistory {
|
||||
for _, history := range history {
|
||||
// TODO: for now we assume revisions don't overlap, we may need to handle it
|
||||
historyInfo[history.Revision] = history
|
||||
}
|
||||
|
||||
if len(historyInfo) == 0 {
|
||||
return "No rollout history found.", nil
|
||||
}
|
||||
@@ -176,13 +173,7 @@ func (h *DaemonSetHistoryViewer) ViewHistory(namespace, name string, revision in
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unable to find the specified revision")
|
||||
}
|
||||
|
||||
versionedDS, ok := versionedObj.(*extensionsv1beta1.DaemonSet)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unexpected non-DaemonSet object returned: %v", versionedDS)
|
||||
}
|
||||
|
||||
dsOfHistory, err := applyHistory(versionedDS, history)
|
||||
dsOfHistory, err := applyDaemonSetHistory(ds, history)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to parse history %s", history.Name)
|
||||
}
|
||||
@@ -212,93 +203,46 @@ func (h *DaemonSetHistoryViewer) ViewHistory(namespace, name string, revision in
|
||||
}
|
||||
|
||||
type StatefulSetHistoryViewer struct {
|
||||
c clientset.Interface
|
||||
}
|
||||
|
||||
func getOwner(revision apps.ControllerRevision) *metav1.OwnerReference {
|
||||
ownerRefs := revision.GetOwnerReferences()
|
||||
for i := range ownerRefs {
|
||||
owner := &ownerRefs[i]
|
||||
if owner.Controller != nil && *owner.Controller == true {
|
||||
return owner
|
||||
}
|
||||
}
|
||||
return nil
|
||||
c kubernetes.Interface
|
||||
}
|
||||
|
||||
// ViewHistory returns a list of the revision history of a statefulset
|
||||
// TODO: this should be a describer
|
||||
// TODO: needs to implement detailed revision view
|
||||
func (h *StatefulSetHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) {
|
||||
_, history, err := statefulSetHistory(h.c.AppsV1beta1(), namespace, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sts, err := h.c.Apps().StatefulSets(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to retrieve statefulset %s", err)
|
||||
}
|
||||
selector, err := metav1.LabelSelectorAsSelector(sts.Spec.Selector)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to retrieve statefulset history %s", err)
|
||||
}
|
||||
revisions, err := h.c.Apps().ControllerRevisions(namespace).List(metav1.ListOptions{LabelSelector: selector.String()})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to retrieve statefulset history %s", err)
|
||||
}
|
||||
if len(revisions.Items) <= 0 {
|
||||
if len(history) <= 0 {
|
||||
return "No rollout history found.", nil
|
||||
}
|
||||
revisionNumbers := make([]int64, len(revisions.Items))
|
||||
for i := range revisions.Items {
|
||||
if owner := getOwner(revisions.Items[i]); owner != nil && owner.UID == sts.UID {
|
||||
revisionNumbers[i] = revisions.Items[i].Revision
|
||||
}
|
||||
revisions := make([]int64, len(history))
|
||||
for _, revision := range history {
|
||||
revisions = append(revisions, revision.Revision)
|
||||
}
|
||||
sliceutil.SortInts64(revisionNumbers)
|
||||
sliceutil.SortInts64(revisions)
|
||||
|
||||
return tabbedString(func(out io.Writer) error {
|
||||
fmt.Fprintf(out, "REVISION\n")
|
||||
for _, r := range revisionNumbers {
|
||||
for _, r := range revisions {
|
||||
fmt.Fprintf(out, "%d\n", r)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// controlledHistories returns all ControllerRevisions controlled by the given API object
|
||||
func controlledHistories(apps clientappsv1beta1.AppsV1beta1Interface, extensions clientextensionsv1beta1.ExtensionsV1beta1Interface, namespace, name, kind string) (runtime.Object, []*appsv1beta1.ControllerRevision, error) {
|
||||
var obj runtime.Object
|
||||
var labelSelector *metav1.LabelSelector
|
||||
|
||||
switch kind {
|
||||
case "DaemonSet":
|
||||
ds, err := extensions.DaemonSets(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to retrieve DaemonSet %s: %v", name, err)
|
||||
}
|
||||
labelSelector = ds.Spec.Selector
|
||||
obj = ds
|
||||
case "StatefulSet":
|
||||
ss, err := apps.StatefulSets(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to retrieve StatefulSet %s: %v", name, err)
|
||||
}
|
||||
labelSelector = ss.Spec.Selector
|
||||
obj = ss
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unsupported API object kind: %s", kind)
|
||||
}
|
||||
|
||||
// controlledHistories returns all ControllerRevisions in namespace that selected by selector and owned by accessor
|
||||
func controlledHistory(
|
||||
apps clientappsv1beta1.AppsV1beta1Interface,
|
||||
namespace string,
|
||||
selector labels.Selector,
|
||||
accessor metav1.Object) ([]*appsv1beta1.ControllerRevision, error) {
|
||||
var result []*appsv1beta1.ControllerRevision
|
||||
selector, err := metav1.LabelSelectorAsSelector(labelSelector)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
historyList, err := apps.ControllerRevisions(namespace).List(metav1.ListOptions{LabelSelector: selector.String()})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to obtain accessor for %s named %s: %v", kind, name, err)
|
||||
return nil, err
|
||||
}
|
||||
for i := range historyList.Items {
|
||||
history := historyList.Items[i]
|
||||
@@ -307,16 +251,59 @@ func controlledHistories(apps clientappsv1beta1.AppsV1beta1Interface, extensions
|
||||
result = append(result, &history)
|
||||
}
|
||||
}
|
||||
return obj, result, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// applyHistory returns a specific revision of DaemonSet by applying the given history to a copy of the given DaemonSet
|
||||
func applyHistory(ds *extensionsv1beta1.DaemonSet, history *appsv1beta1.ControllerRevision) (*extensionsv1beta1.DaemonSet, error) {
|
||||
obj, err := legacyscheme.Scheme.New(ds.GroupVersionKind())
|
||||
// daemonSetHistory returns the DaemonSet named name in namespace and all ControllerRevisions in its history.
|
||||
func daemonSetHistory(
|
||||
ext clientextv1beta1.ExtensionsV1beta1Interface,
|
||||
apps clientappsv1beta1.AppsV1beta1Interface,
|
||||
namespace, name string) (*extensionsv1beta1.DaemonSet, []*appsv1beta1.ControllerRevision, error) {
|
||||
ds, err := ext.DaemonSets(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, fmt.Errorf("failed to retrieve DaemonSet %s: %v", name, err)
|
||||
}
|
||||
clone := obj.(*extensionsv1beta1.DaemonSet)
|
||||
selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create selector for DaemonSet %s: %v", ds.Name, err)
|
||||
}
|
||||
accessor, err := meta.Accessor(ds)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create accessor for DaemonSet %s: %v", ds.Name, err)
|
||||
}
|
||||
history, err := controlledHistory(apps, ds.Namespace, selector, accessor)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to find history controlled by DaemonSet %s: %v", ds.Name, err)
|
||||
}
|
||||
return ds, history, nil
|
||||
}
|
||||
|
||||
// statefulSetHistory returns the StatefulSet named name in namespace and all ControllerRevisions in its history.
|
||||
func statefulSetHistory(
|
||||
apps clientappsv1beta1.AppsV1beta1Interface,
|
||||
namespace, name string) (*appsv1beta1.StatefulSet, []*appsv1beta1.ControllerRevision, error) {
|
||||
sts, err := apps.StatefulSets(namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to retrieve Statefulset %s: %s", name, err.Error())
|
||||
}
|
||||
selector, err := metav1.LabelSelectorAsSelector(sts.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create selector for StatefulSet %s: %s", name, err.Error())
|
||||
}
|
||||
accessor, err := meta.Accessor(sts)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to obtain accessor for StatefulSet %s: %s", name, err.Error())
|
||||
}
|
||||
history, err := controlledHistory(apps, namespace, selector, accessor)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to find history controlled by StatefulSet %s: %v", name, err)
|
||||
}
|
||||
return sts, history, nil
|
||||
}
|
||||
|
||||
// applyDaemonSetHistory returns a specific revision of DaemonSet by applying the given history to a copy of the given DaemonSet
|
||||
func applyDaemonSetHistory(ds *extensionsv1beta1.DaemonSet, history *appsv1beta1.ControllerRevision) (*extensionsv1beta1.DaemonSet, error) {
|
||||
clone := ds.DeepCopy()
|
||||
cloneBytes, err := json.Marshal(clone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
Reference in New Issue
Block a user