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