diff --git a/pkg/cmd/openshift-controller-manager/controller/unidling.go b/pkg/cmd/openshift-controller-manager/controller/unidling.go index e6a914c3fb22..90fba829b66d 100644 --- a/pkg/cmd/openshift-controller-manager/controller/unidling.go +++ b/pkg/cmd/openshift-controller-manager/controller/unidling.go @@ -8,6 +8,7 @@ import ( appsclient "github.com/openshift/origin/pkg/apps/generated/internalclientset/typed/apps/internalversion" "github.com/openshift/origin/pkg/cmd/server/bootstrappolicy" unidlingcontroller "github.com/openshift/origin/pkg/unidling/controller" + kubernetes "k8s.io/client-go/kubernetes/typed/core/v1" ) func RunUnidlingController(ctx ControllerContext) (bool, error) { @@ -20,6 +21,11 @@ func RunUnidlingController(ctx ControllerContext) (bool, error) { return false, err } + coreV1Client, err := kubernetes.NewForConfig(clientConfig) + if err != nil { + return false, err + } + scaleNamespacer := appsv1client.NewDelegatingScaleNamespacer(appsClient, ctx.ClientBuilder.ClientOrDie(bootstrappolicy.InfraUnidlingControllerServiceAccountName).ExtensionsV1beta1()) @@ -29,7 +35,7 @@ func RunUnidlingController(ctx ControllerContext) (bool, error) { coreClient, coreClient, appsclient.NewForConfigOrDie(ctx.ClientBuilder.ConfigOrDie(bootstrappolicy.InfraUnidlingControllerServiceAccountName)), - coreClient, + coreV1Client, resyncPeriod, ) diff --git a/pkg/oc/cli/idle/idle.go b/pkg/oc/cli/idle/idle.go index 24f24f8364ed..846764d73579 100644 --- a/pkg/oc/cli/idle/idle.go +++ b/pkg/oc/cli/idle/idle.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/cobra" utilerrors "github.com/openshift/origin/pkg/util/errors" + corev1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -18,11 +19,10 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/client-go/kubernetes" kextensionsclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/api/legacyscheme" - kapi "k8s.io/kubernetes/pkg/apis/core" - kinternalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" @@ -54,23 +54,23 @@ var ( ) type IdleOptions struct { - dryRun bool - + dryRun bool filename string all bool selector string allNamespaces bool - resources string + resources []string cmdFullName string ClientForMappingFn func(*meta.RESTMapping) (resource.RESTClient, error) ClientConfig *rest.Config - ClientSet kinternalclientset.Interface + ClientSet kubernetes.Interface Mapper meta.RESTMapper - nowTime time.Time - svcBuilder *resource.Builder + Builder func() *resource.Builder + Namespace string + nowTime time.Time genericclioptions.IOStreams } @@ -110,7 +110,8 @@ func NewCmdIdle(fullName string, f kcmdutil.Factory, streams genericclioptions.I } func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - namespace, _, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -127,7 +128,7 @@ func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []st return err } - o.ClientSet, err = f.ClientSet() + o.ClientSet, err = kubernetes.NewForConfig(o.ClientConfig) if err != nil { return err } @@ -138,32 +139,9 @@ func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []st } o.ClientForMappingFn = f.ClientForMapping + o.Builder = f.NewBuilder - o.svcBuilder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). - ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace().AllNamespaces(o.allNamespaces). - Flatten(). - SingleResourceType() - - if len(o.filename) > 0 { - targetServiceNames, err := scanLinesFromFile(o.filename) - if err != nil { - return err - } - o.svcBuilder.ResourceNames("endpoints", targetServiceNames...) - } else { - // NB: this is a bit weird because the resource builder will complain if we use ResourceTypes and ResourceNames when len(args) > 0 - if o.selector != "" { - o.svcBuilder.LabelSelectorParam(o.selector).ResourceTypes("endpoints") - } - - o.svcBuilder.ResourceNames("endpoints", args...) - - if o.all { - o.svcBuilder.ResourceTypes("endpoints").SelectAllParam(o.all) - } - } + o.resources = args return nil } @@ -206,7 +184,7 @@ func scanLinesFromFile(filename string) ([]string, error) { // idleUpdateInfo contains the required info to annotate an endpoints object // with the scalable resources that it should unidle type idleUpdateInfo struct { - obj *kapi.Endpoints + obj *corev1.Endpoints scaleRefs map[unidlingapi.CrossGroupObjectReference]struct{} } @@ -224,9 +202,9 @@ type controllerRef struct { // Using the list of services, it figures out the associated scalable objects, and returns a map from the endpoints object for the services to // the list of scalable resources associated with that endpoints object, as well as a map from CrossGroupObjectReferences to scale to 0 to the // name of the associated service. -func (o *IdleOptions) calculateIdlableAnnotationsByService() (map[types.NamespacedName]idleUpdateInfo, map[namespacedCrossGroupObjectReference]types.NamespacedName, error) { - podsLoaded := make(map[kapi.ObjectReference]*kapi.Pod) - getPod := func(ref kapi.ObjectReference) (*kapi.Pod, error) { +func (o *IdleOptions) calculateIdlableAnnotationsByService(infoVisitor func(resource.VisitorFunc) error) (map[types.NamespacedName]idleUpdateInfo, map[namespacedCrossGroupObjectReference]types.NamespacedName, error) { + podsLoaded := make(map[corev1.ObjectReference]*corev1.Pod) + getPod := func(ref corev1.ObjectReference) (*corev1.Pod, error) { if pod, ok := podsLoaded[ref]; ok { return pod, nil } @@ -287,12 +265,12 @@ func (o *IdleOptions) calculateIdlableAnnotationsByService() (map[types.Namespac targetScaleRefs := make(map[namespacedCrossGroupObjectReference]types.NamespacedName) endpointsInfo := make(map[types.NamespacedName]idleUpdateInfo) - err := o.svcBuilder.Do().Visit(func(info *resource.Info, err error) error { + err := infoVisitor(func(info *resource.Info, err error) error { if err != nil { return err } - endpoints, isEndpoints := info.Object.(*kapi.Endpoints) + endpoints, isEndpoints := info.Object.(*corev1.Endpoints) if !isEndpoints { return fmt.Errorf("you must specify endpoints, not %v (view available endpoints with \"%s get endpoints\").", info.Mapping.Resource, o.cmdFullName) } @@ -372,9 +350,9 @@ func normalizedNSOwnerRef(namespace string, ownerRef *metav1.OwnerReference) nam // scalable objects by checking each address in each subset to see if it has a pod // reference, and the following that pod reference to find the owning controller, // and returning the unique set of controllers found this way. -func findScalableResourcesForEndpoints(endpoints *kapi.Endpoints, getPod func(kapi.ObjectReference) (*kapi.Pod, error), getController func(namespacedOwnerReference) (metav1.Object, error)) (map[namespacedCrossGroupObjectReference]struct{}, error) { +func findScalableResourcesForEndpoints(endpoints *corev1.Endpoints, getPod func(corev1.ObjectReference) (*corev1.Pod, error), getController func(namespacedOwnerReference) (metav1.Object, error)) (map[namespacedCrossGroupObjectReference]struct{}, error) { // To find all RCs and DCs for an endpoint, we first figure out which pods are pointed to by that endpoint... - podRefs := map[kapi.ObjectReference]*kapi.Pod{} + podRefs := map[corev1.ObjectReference]*corev1.Pod{} for _, subset := range endpoints.Subsets { for _, addr := range subset.Addresses { if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" { @@ -547,6 +525,32 @@ type scaleInfo struct { // scalable resources to zero, and annotating the associated endpoints objects with the scalable resources to unidle // when they receive traffic. func (o *IdleOptions) RunIdle() error { + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.allNamespaces). + Flatten(). + SingleResourceType() + + if len(o.filename) > 0 { + targetServiceNames, err := scanLinesFromFile(o.filename) + if err != nil { + return err + } + b.ResourceNames("endpoints", targetServiceNames...) + } else { + // NB: this is a bit weird because the resource builder will complain if we use ResourceTypes and ResourceNames when len(args) > 0 + if o.selector != "" { + b.LabelSelectorParam(o.selector).ResourceTypes("endpoints") + } + + b.ResourceNames("endpoints", o.resources...) + + if o.all { + b.ResourceTypes("endpoints").SelectAllParam(o.all) + } + } + hadError := false nowTime := time.Now().UTC() @@ -556,7 +560,7 @@ func (o *IdleOptions) RunIdle() error { } // figure out which endpoints and resources we need to idle - byService, byScalable, err := o.calculateIdlableAnnotationsByService() + byService, byScalable, err := o.calculateIdlableAnnotationsByService(b.Do().Visit) if err != nil { if len(byService) == 0 || len(byScalable) == 0 { diff --git a/pkg/unidling/controller/unidling_controller.go b/pkg/unidling/controller/unidling_controller.go index 60db86a1827d..9e4f61cdd00f 100644 --- a/pkg/unidling/controller/unidling_controller.go +++ b/pkg/unidling/controller/unidling_controller.go @@ -20,6 +20,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + kubernetes "k8s.io/client-go/kubernetes/typed/core/v1" kextclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" "k8s.io/client-go/tools/cache" kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" @@ -73,10 +74,10 @@ type UnidlingController struct { // TODO: remove these once we get the scale-source functionality in the scale endpoints dcNamespacer appsclient.DeploymentConfigsGetter - rcNamespacer kcoreclient.ReplicationControllersGetter + rcNamespacer kubernetes.ReplicationControllersGetter } -func NewUnidlingController(scaleNS kextclient.ScalesGetter, endptsNS kcoreclient.EndpointsGetter, evtNS kcoreclient.EventsGetter, dcNamespacer appsclient.DeploymentConfigsGetter, rcNamespacer kcoreclient.ReplicationControllersGetter, resyncPeriod time.Duration) *UnidlingController { +func NewUnidlingController(scaleNS kextclient.ScalesGetter, endptsNS kcoreclient.EndpointsGetter, evtNS kcoreclient.EventsGetter, dcNamespacer appsclient.DeploymentConfigsGetter, rcNamespacer kubernetes.ReplicationControllersGetter, resyncPeriod time.Duration) *UnidlingController { fieldSet := fields.Set{} fieldSet["reason"] = unidlingapi.NeedPodsReason fieldSelector := fieldSet.AsSelector() diff --git a/pkg/unidling/util/scale.go b/pkg/unidling/util/scale.go index c93e99ec284b..4b3807da3fde 100644 --- a/pkg/unidling/util/scale.go +++ b/pkg/unidling/util/scale.go @@ -3,15 +3,15 @@ package util import ( "github.com/golang/glog" - kapiv1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" kextapi "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/strategicpatch" + kubernetes "k8s.io/client-go/kubernetes/typed/core/v1" kextensionsclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" kapi "k8s.io/kubernetes/pkg/apis/core" - kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" appsapiv1 "github.com/openshift/api/apps/v1" appsapi "github.com/openshift/origin/pkg/apps/apis/apps" @@ -24,7 +24,7 @@ import ( type AnnotationFunc func(currentReplicas int32, annotations map[string]string) -func NewScaleAnnotater(scales kextensionsclient.ScalesGetter, dcs appsclient.DeploymentConfigsGetter, rcs kcoreclient.ReplicationControllersGetter, changeAnnots AnnotationFunc) *ScaleAnnotater { +func NewScaleAnnotater(scales kextensionsclient.ScalesGetter, dcs appsclient.DeploymentConfigsGetter, rcs kubernetes.ReplicationControllersGetter, changeAnnots AnnotationFunc) *ScaleAnnotater { return &ScaleAnnotater{ scales: scales, dcs: dcs, @@ -36,7 +36,7 @@ func NewScaleAnnotater(scales kextensionsclient.ScalesGetter, dcs appsclient.Dep type ScaleAnnotater struct { scales kextensionsclient.ScalesGetter dcs appsclient.DeploymentConfigsGetter - rcs kcoreclient.ReplicationControllersGetter + rcs kubernetes.ReplicationControllersGetter ChangeAnnotations AnnotationFunc } @@ -50,10 +50,10 @@ type scaleUpdater struct { encoder runtime.Encoder namespace string dcGetter appsclient.DeploymentConfigsGetter - rcGetter kcoreclient.ReplicationControllersGetter + rcGetter kubernetes.ReplicationControllersGetter } -func NewScaleUpdater(encoder runtime.Encoder, namespace string, dcGetter appsclient.DeploymentConfigsGetter, rcGetter kcoreclient.ReplicationControllersGetter) ScaleUpdater { +func NewScaleUpdater(encoder runtime.Encoder, namespace string, dcGetter appsclient.DeploymentConfigsGetter, rcGetter kubernetes.ReplicationControllersGetter) ScaleUpdater { return scaleUpdater{ encoder: encoder, namespace: namespace, @@ -106,7 +106,7 @@ func (s scaleUpdater) Update(annotator *ScaleAnnotater, obj runtime.Object, scal return err } - patchBytes, err = strategicpatch.CreateTwoWayMergePatch(originalObj, newObj, &kapiv1.ReplicationController{}) + patchBytes, err = strategicpatch.CreateTwoWayMergePatch(originalObj, newObj, &corev1.ReplicationController{}) if err != nil { return err } @@ -135,13 +135,13 @@ func (c *ScaleAnnotater) GetObjectWithScale(namespace string, ref unidlingapi.Cr } obj = dc case ref.Kind == "ReplicationController" && ref.Group == kapi.GroupName: - var rc *kapi.ReplicationController + var rc *corev1.ReplicationController rc, err = c.rcs.ReplicationControllers(namespace).Get(ref.Name, metav1.GetOptions{}) if err != nil { return nil, nil, err } scale = &kextapi.Scale{ - Spec: kextapi.ScaleSpec{Replicas: rc.Spec.Replicas}, + Spec: kextapi.ScaleSpec{Replicas: *rc.Spec.Replicas}, } obj = rc default: