Skip to content

Commit 7dfb20f

Browse files
author
Scott Nichols
committed
move enable injeciton out of sharedmain
1 parent 11f5e2d commit 7dfb20f

File tree

5 files changed

+157
-45
lines changed

5 files changed

+157
-45
lines changed

injection/config.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
Copyright 2020 The Knative Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package injection
18+
19+
import (
20+
"errors"
21+
"flag"
22+
"k8s.io/client-go/rest"
23+
"k8s.io/client-go/tools/clientcmd"
24+
"k8s.io/klog"
25+
"log"
26+
"os"
27+
"os/user"
28+
"path/filepath"
29+
)
30+
31+
// ParseAndGetRestConfigOrDie parses the rest config flags and creates a client or
32+
// dies by calling log.Fatalf.
33+
func ParseAndGetRestConfigOrDie() *rest.Config {
34+
var (
35+
serverURL = flag.String("server", "",
36+
"The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
37+
kubeconfig = flag.String("kubeconfig", "",
38+
"Path to a kubeconfig. Only required if out-of-cluster.")
39+
)
40+
klog.InitFlags(flag.CommandLine)
41+
flag.Parse()
42+
43+
cfg, err := GetRestConfig(*serverURL, *kubeconfig)
44+
if err != nil {
45+
log.Fatalf("Error building kubeconfig: %v", err)
46+
}
47+
48+
return cfg
49+
}
50+
51+
// GetConfig returns a rest.Config to be used for kubernetes client creation.
52+
// It does so in the following order:
53+
// 1. Use the passed kubeconfig/serverURL.
54+
// 2. Fallback to the KUBECONFIG environment variable.
55+
// 3. Fallback to in-cluster config.
56+
// 4. Fallback to the ~/.kube/config.
57+
func GetRestConfig(serverURL, kubeconfig string) (*rest.Config, error) {
58+
if kubeconfig == "" {
59+
kubeconfig = os.Getenv("KUBECONFIG")
60+
}
61+
62+
// We produce configs a bunch of ways, this gives us a single place
63+
// to "decorate" them with common useful things (e.g. for debugging)
64+
decorate := func(cfg *rest.Config) *rest.Config {
65+
return cfg
66+
}
67+
68+
// If we have an explicit indication of where the kubernetes config lives, read that.
69+
if kubeconfig != "" {
70+
c, err := clientcmd.BuildConfigFromFlags(serverURL, kubeconfig)
71+
if err != nil {
72+
return nil, err
73+
}
74+
return decorate(c), nil
75+
}
76+
// If not, try the in-cluster config.
77+
if c, err := rest.InClusterConfig(); err == nil {
78+
return decorate(c), nil
79+
}
80+
// If no in-cluster config, try the default location in the user's home directory.
81+
if usr, err := user.Current(); err == nil {
82+
if c, err := clientcmd.BuildConfigFromFlags("", filepath.Join(usr.HomeDir, ".kube", "config")); err == nil {
83+
return decorate(c), nil
84+
}
85+
}
86+
87+
return nil, errors.New("could not create a valid kubeconfig")
88+
}

injection/context.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package injection
1818

1919
import (
2020
"context"
21-
2221
"k8s.io/client-go/rest"
2322
)
2423

injection/injection.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2019 The Knative Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package injection
18+
19+
import (
20+
"context"
21+
"go.uber.org/zap"
22+
"knative.dev/pkg/controller"
23+
"knative.dev/pkg/logging"
24+
"knative.dev/pkg/signals"
25+
26+
"k8s.io/client-go/rest"
27+
)
28+
29+
// EnableInjectionOrDie enables Knative Injection and starts the informers.
30+
// Both Context and Config are optional. Returns context with rest config set
31+
// and a function to start the informers after watches have been set up.
32+
func EnableInjectionOrDie(ctx context.Context, cfg *rest.Config) (context.Context, func()) {
33+
if ctx == nil {
34+
ctx = signals.NewContext()
35+
}
36+
if cfg == nil {
37+
cfg = ParseAndGetRestConfigOrDie()
38+
}
39+
40+
// Respect user provided settings, but if omitted customize the default behavior.
41+
if cfg.QPS == 0 {
42+
cfg.QPS = rest.DefaultQPS
43+
}
44+
if cfg.Burst == 0 {
45+
cfg.Burst = rest.DefaultBurst
46+
}
47+
ctx = WithConfig(ctx, cfg)
48+
49+
ctx, informers := Default.SetupInformers(ctx, cfg)
50+
51+
return ctx, func() {
52+
logging.FromContext(ctx).Info("Starting informers...")
53+
if err := controller.StartInformers(ctx.Done(), informers...); err != nil {
54+
logging.FromContext(ctx).Fatalw("Failed to start informers", zap.Error(err))
55+
}
56+
}
57+
}

injection/sharedmain/main.go

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"os"
2626
"os/user"
2727
"path/filepath"
28-
"reflect"
2928
"time"
3029

3130
"go.opencensus.io/stats/view"
@@ -64,6 +63,7 @@ import (
6463
// 2. Fallback to the KUBECONFIG environment variable.
6564
// 3. Fallback to in-cluster config.
6665
// 4. Fallback to the ~/.kube/config.
66+
// Deprecated: use injection.GetRestConfig
6767
func GetConfig(serverURL, kubeconfig string) (*rest.Config, error) {
6868
if kubeconfig == "" {
6969
kubeconfig = os.Getenv("KUBECONFIG")
@@ -128,40 +128,15 @@ func GetLeaderElectionConfig(ctx context.Context) (*leaderelection.Config, error
128128
return leaderelection.NewConfigFromConfigMap(leaderElectionConfigMap)
129129
}
130130

131-
const (
132-
defaultStartInformerDelayTime = 5 * time.Second
133-
)
134-
135-
type informerStartChanKey struct{}
136-
type informerStartTimeoutKey struct{}
137-
138-
func WithInformerStart(ctx context.Context, start <-chan struct{}, timeout time.Duration) context.Context {
139-
ctx = context.WithValue(ctx, informerStartChanKey{}, start)
140-
return context.WithValue(ctx, informerStartTimeoutKey{}, timeout)
141-
}
142-
143-
func getInformerStartChanTimeout(ctx context.Context) (<-chan struct{}, time.Duration) {
144-
timeout := defaultStartInformerDelayTime
145-
tuntyped := ctx.Value(informerStartTimeoutKey{})
146-
if tuntyped != nil {
147-
timeout = tuntyped.(time.Duration)
148-
}
149-
150-
untyped := ctx.Value(informerStartChanKey{})
151-
if untyped == nil || reflect.ValueOf(untyped).IsNil() {
152-
return make(chan struct{}, 1), timeout
153-
}
154-
return untyped.(<-chan struct{}), timeout
155-
}
156-
157131
// EnableInjectionOrDie enables Knative Injection and starts the informers.
158132
// Both Context and Config are optional.
133+
// Deprecated: use injection.EnableInjectionOrDie
159134
func EnableInjectionOrDie(ctx context.Context, cfg *rest.Config) context.Context {
160135
if ctx == nil {
161136
ctx = signals.NewContext()
162137
}
163138
if cfg == nil {
164-
cfg = ParseAndGetConfigOrDie()
139+
cfg = injection.ParseAndGetRestConfigOrDie()
165140
}
166141

167142
// Respect user provided settings, but if omitted customize the default behavior.
@@ -175,13 +150,7 @@ func EnableInjectionOrDie(ctx context.Context, cfg *rest.Config) context.Context
175150

176151
ctx, informers := injection.Default.SetupInformers(ctx, cfg)
177152

178-
start, timeout := getInformerStartChanTimeout(ctx)
179153
go func() {
180-
// Block until the timeout or we are told it is ok to start informers.
181-
select {
182-
case <-start:
183-
case <-time.After(timeout):
184-
}
185154
logging.FromContext(ctx).Info("Starting informers...")
186155
if err := controller.StartInformers(ctx.Done(), informers...); err != nil {
187156
logging.FromContext(ctx).Fatalw("Failed to start informers", zap.Error(err))
@@ -192,8 +161,8 @@ func EnableInjectionOrDie(ctx context.Context, cfg *rest.Config) context.Context
192161
}
193162

194163
// Main runs the generic main flow with a new context.
195-
// If any of the contructed controllers are AdmissionControllers or Conversion webhooks,
196-
// then a webhook is started to serve them.
164+
// If any of the constructed controllers are AdmissionControllers or Conversion
165+
// webhooks, then a webhook is started to serve them.
197166
func Main(component string, ctors ...injection.ControllerConstructor) {
198167
// Set up signals so we handle the first shutdown signal gracefully.
199168
MainWithContext(signals.NewContext(), component, ctors...)
@@ -216,7 +185,7 @@ func MainWithContext(ctx context.Context, component string, ctors ...injection.C
216185
"issue upstream!")
217186

218187
// HACK: This parses flags, so the above should be set once this runs.
219-
cfg := ParseAndGetConfigOrDie()
188+
cfg := injection.ParseAndGetRestConfigOrDie()
220189

221190
if *disableHighAvailability {
222191
ctx = WithHADisabled(ctx)
@@ -256,8 +225,7 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
256225
cfg.Burst = len(ctors) * rest.DefaultBurst
257226
}
258227

259-
startCh := make(chan struct{}, 1)
260-
ctx = EnableInjectionOrDie(WithInformerStart(ctx, startCh, defaultStartInformerDelayTime), cfg)
228+
ctx, startInformers := injection.EnableInjectionOrDie(ctx, cfg)
261229

262230
logger, atomicLevel := SetupLoggerOrDie(ctx, component)
263231
defer flush(logger)
@@ -312,7 +280,7 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
312280
}
313281

314282
// Start the injection clients and informers.
315-
startCh <- struct{}{}
283+
startInformers()
316284

317285
// Wait for webhook informers to sync.
318286
if wh != nil {
@@ -339,6 +307,7 @@ func flush(logger *zap.SugaredLogger) {
339307

340308
// ParseAndGetConfigOrDie parses the rest config flags and creates a client or
341309
// dies by calling log.Fatalf.
310+
// Deprecated: use injeciton.ParseAndGetRestConfigOrDie
342311
func ParseAndGetConfigOrDie() *rest.Config {
343312
var (
344313
serverURL = flag.String("server", "",
@@ -349,7 +318,7 @@ func ParseAndGetConfigOrDie() *rest.Config {
349318
klog.InitFlags(flag.CommandLine)
350319
flag.Parse()
351320

352-
cfg, err := GetConfig(*serverURL, *kubeconfig)
321+
cfg, err := injection.GetRestConfig(*serverURL, *kubeconfig)
353322
if err != nil {
354323
log.Fatalf("Error building kubeconfig: %v", err)
355324
}

leaderelection/chaosduck/main.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"context"
2424
"errors"
2525
"flag"
26+
"knative.dev/pkg/injection"
2627
"log"
2728
"strings"
2829
"time"
@@ -33,7 +34,6 @@ import (
3334
"k8s.io/apimachinery/pkg/util/wait"
3435
"k8s.io/client-go/kubernetes"
3536
kubeclient "knative.dev/pkg/client/injection/kube/client"
36-
"knative.dev/pkg/injection/sharedmain"
3737
"knative.dev/pkg/kflag"
3838
"knative.dev/pkg/signals"
3939
"knative.dev/pkg/system"
@@ -116,8 +116,7 @@ func quack(ctx context.Context, kc kubernetes.Interface, component string, leade
116116
}
117117

118118
func main() {
119-
ctx := signals.NewContext()
120-
ctx = sharedmain.EnableInjectionOrDie(ctx, nil)
119+
ctx, _ := injection.EnableInjectionOrDie(signals.NewContext(), nil)
121120

122121
kc := kubeclient.Get(ctx)
123122

0 commit comments

Comments
 (0)