@@ -11,18 +11,18 @@ import (
11
11
"github.com/spf13/cobra"
12
12
13
13
utilerrors "github.com/openshift/origin/pkg/util/errors"
14
+ corev1 "k8s.io/api/core/v1"
14
15
extensions "k8s.io/api/extensions/v1beta1"
15
16
"k8s.io/apimachinery/pkg/api/meta"
16
17
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
18
"k8s.io/apimachinery/pkg/runtime"
18
19
"k8s.io/apimachinery/pkg/runtime/schema"
19
20
"k8s.io/apimachinery/pkg/types"
20
21
"k8s.io/apimachinery/pkg/util/strategicpatch"
22
+ clientset "k8s.io/client-go/kubernetes"
21
23
kextensionsclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
22
24
"k8s.io/client-go/rest"
23
25
"k8s.io/kubernetes/pkg/api/legacyscheme"
24
- kapi "k8s.io/kubernetes/pkg/apis/core"
25
- kinternalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
26
26
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
27
27
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
28
28
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
@@ -34,6 +34,7 @@ import (
34
34
"github.com/openshift/origin/pkg/oc/util/ocscheme"
35
35
unidlingapi "github.com/openshift/origin/pkg/unidling/api"
36
36
utilunidling "github.com/openshift/origin/pkg/unidling/util"
37
+ kinternalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
37
38
)
38
39
39
40
var (
@@ -54,23 +55,26 @@ var (
54
55
)
55
56
56
57
type IdleOptions struct {
57
- dryRun bool
58
-
58
+ dryRun bool
59
59
filename string
60
60
all bool
61
61
selector string
62
62
allNamespaces bool
63
- resources string
63
+ resources [] string
64
64
65
65
cmdFullName string
66
66
67
67
ClientForMappingFn func (* meta.RESTMapping ) (resource.RESTClient , error )
68
68
ClientConfig * rest.Config
69
- ClientSet kinternalclientset .Interface
69
+ ClientSet clientset .Interface
70
70
Mapper meta.RESTMapper
71
71
72
- nowTime time.Time
73
- svcBuilder * resource.Builder
72
+ // TODO(juanvallejo): remove this once we switch unidling helpers to use external versions
73
+ InternalClientset kinternalclientset.Interface
74
+
75
+ Builder func () * resource.Builder
76
+ Namespace string
77
+ nowTime time.Time
74
78
75
79
genericclioptions.IOStreams
76
80
}
@@ -110,7 +114,8 @@ func NewCmdIdle(fullName string, f kcmdutil.Factory, streams genericclioptions.I
110
114
}
111
115
112
116
func (o * IdleOptions ) Complete (f kcmdutil.Factory , cmd * cobra.Command , args []string ) error {
113
- namespace , _ , err := f .ToRawKubeConfigLoader ().Namespace ()
117
+ var err error
118
+ o .Namespace , _ , err = f .ToRawKubeConfigLoader ().Namespace ()
114
119
if err != nil {
115
120
return err
116
121
}
@@ -127,7 +132,7 @@ func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []st
127
132
return err
128
133
}
129
134
130
- o .ClientSet , err = f . ClientSet ( )
135
+ o .ClientSet , err = clientset . NewForConfig ( o . ClientConfig )
131
136
if err != nil {
132
137
return err
133
138
}
@@ -137,33 +142,15 @@ func (o *IdleOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []st
137
142
return err
138
143
}
139
144
140
- o .ClientForMappingFn = f .ClientForMapping
141
-
142
- o .svcBuilder = f .NewBuilder ().
143
- WithScheme (ocscheme .ReadingInternalScheme ).
144
- ContinueOnError ().
145
- NamespaceParam (namespace ).DefaultNamespace ().AllNamespaces (o .allNamespaces ).
146
- Flatten ().
147
- SingleResourceType ()
148
-
149
- if len (o .filename ) > 0 {
150
- targetServiceNames , err := scanLinesFromFile (o .filename )
151
- if err != nil {
152
- return err
153
- }
154
- o .svcBuilder .ResourceNames ("endpoints" , targetServiceNames ... )
155
- } else {
156
- // NB: this is a bit weird because the resource builder will complain if we use ResourceTypes and ResourceNames when len(args) > 0
157
- if o .selector != "" {
158
- o .svcBuilder .LabelSelectorParam (o .selector ).ResourceTypes ("endpoints" )
159
- }
145
+ o .InternalClientset , err = f .ClientSet ()
146
+ if err != nil {
147
+ return err
148
+ }
160
149
161
- o .svcBuilder .ResourceNames ("endpoints" , args ... )
150
+ o .ClientForMappingFn = f .ClientForMapping
151
+ o .Builder = f .NewBuilder
162
152
163
- if o .all {
164
- o .svcBuilder .ResourceTypes ("endpoints" ).SelectAllParam (o .all )
165
- }
166
- }
153
+ o .resources = args
167
154
168
155
return nil
169
156
}
@@ -206,7 +193,7 @@ func scanLinesFromFile(filename string) ([]string, error) {
206
193
// idleUpdateInfo contains the required info to annotate an endpoints object
207
194
// with the scalable resources that it should unidle
208
195
type idleUpdateInfo struct {
209
- obj * kapi .Endpoints
196
+ obj * corev1 .Endpoints
210
197
scaleRefs map [unidlingapi.CrossGroupObjectReference ]struct {}
211
198
}
212
199
@@ -224,9 +211,9 @@ type controllerRef struct {
224
211
// Using the list of services, it figures out the associated scalable objects, and returns a map from the endpoints object for the services to
225
212
// the list of scalable resources associated with that endpoints object, as well as a map from CrossGroupObjectReferences to scale to 0 to the
226
213
// name of the associated service.
227
- func (o * IdleOptions ) calculateIdlableAnnotationsByService () (map [types.NamespacedName ]idleUpdateInfo , map [namespacedCrossGroupObjectReference ]types.NamespacedName , error ) {
228
- podsLoaded := make (map [kapi .ObjectReference ]* kapi .Pod )
229
- getPod := func (ref kapi .ObjectReference ) (* kapi .Pod , error ) {
214
+ func (o * IdleOptions ) calculateIdlableAnnotationsByService (infoVisitor func (resource. VisitorFunc ) error ) (map [types.NamespacedName ]idleUpdateInfo , map [namespacedCrossGroupObjectReference ]types.NamespacedName , error ) {
215
+ podsLoaded := make (map [corev1 .ObjectReference ]* corev1 .Pod )
216
+ getPod := func (ref corev1 .ObjectReference ) (* corev1 .Pod , error ) {
230
217
if pod , ok := podsLoaded [ref ]; ok {
231
218
return pod , nil
232
219
}
@@ -287,12 +274,12 @@ func (o *IdleOptions) calculateIdlableAnnotationsByService() (map[types.Namespac
287
274
targetScaleRefs := make (map [namespacedCrossGroupObjectReference ]types.NamespacedName )
288
275
endpointsInfo := make (map [types.NamespacedName ]idleUpdateInfo )
289
276
290
- err := o . svcBuilder . Do (). Visit (func (info * resource.Info , err error ) error {
277
+ err := infoVisitor (func (info * resource.Info , err error ) error {
291
278
if err != nil {
292
279
return err
293
280
}
294
281
295
- endpoints , isEndpoints := info .Object .(* kapi .Endpoints )
282
+ endpoints , isEndpoints := info .Object .(* corev1 .Endpoints )
296
283
if ! isEndpoints {
297
284
return fmt .Errorf ("you must specify endpoints, not %v (view available endpoints with \" %s get endpoints\" )." , info .Mapping .Resource , o .cmdFullName )
298
285
}
@@ -372,9 +359,9 @@ func normalizedNSOwnerRef(namespace string, ownerRef *metav1.OwnerReference) nam
372
359
// scalable objects by checking each address in each subset to see if it has a pod
373
360
// reference, and the following that pod reference to find the owning controller,
374
361
// and returning the unique set of controllers found this way.
375
- func findScalableResourcesForEndpoints (endpoints * kapi .Endpoints , getPod func (kapi .ObjectReference ) (* kapi .Pod , error ), getController func (namespacedOwnerReference ) (metav1.Object , error )) (map [namespacedCrossGroupObjectReference ]struct {}, error ) {
362
+ func findScalableResourcesForEndpoints (endpoints * corev1 .Endpoints , getPod func (corev1 .ObjectReference ) (* corev1 .Pod , error ), getController func (namespacedOwnerReference ) (metav1.Object , error )) (map [namespacedCrossGroupObjectReference ]struct {}, error ) {
376
363
// To find all RCs and DCs for an endpoint, we first figure out which pods are pointed to by that endpoint...
377
- podRefs := map [kapi .ObjectReference ]* kapi .Pod {}
364
+ podRefs := map [corev1 .ObjectReference ]* corev1 .Pod {}
378
365
for _ , subset := range endpoints .Subsets {
379
366
for _ , addr := range subset .Addresses {
380
367
if addr .TargetRef != nil && addr .TargetRef .Kind == "Pod" {
@@ -547,6 +534,32 @@ type scaleInfo struct {
547
534
// scalable resources to zero, and annotating the associated endpoints objects with the scalable resources to unidle
548
535
// when they receive traffic.
549
536
func (o * IdleOptions ) RunIdle () error {
537
+ b := o .Builder ().
538
+ WithScheme (ocscheme .ReadingInternalScheme , ocscheme .ReadingInternalScheme .PrioritizedVersionsAllGroups ()... ).
539
+ ContinueOnError ().
540
+ NamespaceParam (o .Namespace ).DefaultNamespace ().AllNamespaces (o .allNamespaces ).
541
+ Flatten ().
542
+ SingleResourceType ()
543
+
544
+ if len (o .filename ) > 0 {
545
+ targetServiceNames , err := scanLinesFromFile (o .filename )
546
+ if err != nil {
547
+ return err
548
+ }
549
+ b .ResourceNames ("endpoints" , targetServiceNames ... )
550
+ } else {
551
+ // NB: this is a bit weird because the resource builder will complain if we use ResourceTypes and ResourceNames when len(args) > 0
552
+ if o .selector != "" {
553
+ b .LabelSelectorParam (o .selector ).ResourceTypes ("endpoints" )
554
+ }
555
+
556
+ b .ResourceNames ("endpoints" , o .resources ... )
557
+
558
+ if o .all {
559
+ b .ResourceTypes ("endpoints" ).SelectAllParam (o .all )
560
+ }
561
+ }
562
+
550
563
hadError := false
551
564
nowTime := time .Now ().UTC ()
552
565
@@ -556,7 +569,7 @@ func (o *IdleOptions) RunIdle() error {
556
569
}
557
570
558
571
// figure out which endpoints and resources we need to idle
559
- byService , byScalable , err := o .calculateIdlableAnnotationsByService ()
572
+ byService , byScalable , err := o .calculateIdlableAnnotationsByService (b . Do (). Visit )
560
573
561
574
if err != nil {
562
575
if len (byService ) == 0 || len (byScalable ) == 0 {
@@ -576,7 +589,7 @@ func (o *IdleOptions) RunIdle() error {
576
589
577
590
externalKubeExtensionClient := kextensionsclient .New (o .ClientSet .Extensions ().RESTClient ())
578
591
delegScaleGetter := appsmanualclient .NewDelegatingScaleNamespacer (appsV1Client , externalKubeExtensionClient )
579
- scaleAnnotater := utilunidling .NewScaleAnnotater (delegScaleGetter , appClient .Apps (), o .ClientSet .Core (), func (currentReplicas int32 , annotations map [string ]string ) {
592
+ scaleAnnotater := utilunidling .NewScaleAnnotater (delegScaleGetter , appClient .Apps (), o .InternalClientset .Core (), func (currentReplicas int32 , annotations map [string ]string ) {
580
593
annotations [unidlingapi .IdledAtAnnotation ] = nowTime .UTC ().Format (time .RFC3339 )
581
594
annotations [unidlingapi .PreviousScaleAnnotation ] = fmt .Sprintf ("%v" , currentReplicas )
582
595
})
@@ -679,7 +692,7 @@ func (o *IdleOptions) RunIdle() error {
679
692
for scaleRef , info := range toScale {
680
693
if ! o .dryRun {
681
694
info .scale .Spec .Replicas = 0
682
- scaleUpdater := utilunidling .NewScaleUpdater (kcmdutil .InternalVersionJSONEncoder (), info .namespace , appClient .Apps (), o .ClientSet .Core ())
695
+ scaleUpdater := utilunidling .NewScaleUpdater (kcmdutil .InternalVersionJSONEncoder (), info .namespace , appClient .Apps (), o .InternalClientset .Core ())
683
696
if err := scaleAnnotater .UpdateObjectScale (scaleUpdater , info .namespace , scaleRef .CrossGroupObjectReference , info .obj , info .scale ); err != nil {
684
697
fmt .Fprintf (o .ErrOut , "error: unable to scale %s %s/%s to 0, but still listed as target for unidling: %v\n " , scaleRef .Kind , info .namespace , scaleRef .Name , err )
685
698
hadError = true
0 commit comments