• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Azure / aks-app-routing-operator / 12891069673

21 Jan 2025 04:10PM UTC coverage: 75.936% (-2.7%) from 78.62%
12891069673

push

github

web-flow
Merge branch 'main' into jkatariya/crd-externaldns

1 of 1 new or added line in 1 file covered. (100.0%)

309 existing lines in 11 files now uncovered.

3206 of 4222 relevant lines covered (75.94%)

34.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

21.56
/pkg/controller/controller.go
1
// Copyright (c) Microsoft Corporation.
2
// Licensed under the MIT License.
3

4
package controller
5

6
import (
7
        "context"
8
        "fmt"
9
        "net/http"
10

11
        approutingv1alpha1 "github.com/Azure/aks-app-routing-operator/api/v1alpha1"
12
        "github.com/Azure/aks-app-routing-operator/pkg/controller/nginxingress"
13
        "github.com/Azure/aks-app-routing-operator/pkg/controller/service"
14
        "github.com/go-logr/logr"
15
        cfgv1alpha2 "github.com/openservicemesh/osm/pkg/apis/config/v1alpha2"
16
        policyv1alpha1 "github.com/openservicemesh/osm/pkg/apis/policy/v1alpha1"
17
        ubzap "go.uber.org/zap"
18
        appsv1 "k8s.io/api/apps/v1"
19
        netv1 "k8s.io/api/networking/v1"
20
        apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
21
        "k8s.io/apimachinery/pkg/api/errors"
22
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
        "k8s.io/apimachinery/pkg/runtime"
24
        utilruntime "k8s.io/apimachinery/pkg/util/runtime"
25
        "k8s.io/client-go/kubernetes"
26
        clientgoscheme "k8s.io/client-go/kubernetes/scheme"
27
        "k8s.io/client-go/rest"
28
        "k8s.io/klog/v2"
29
        ctrl "sigs.k8s.io/controller-runtime"
30
        "sigs.k8s.io/controller-runtime/pkg/client"
31
        "sigs.k8s.io/controller-runtime/pkg/log/zap"
32
        metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
33
        secv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
34

35
        "github.com/Azure/aks-app-routing-operator/pkg/config"
36
        "github.com/Azure/aks-app-routing-operator/pkg/controller/dns"
37
        "github.com/Azure/aks-app-routing-operator/pkg/controller/ingress"
38
        "github.com/Azure/aks-app-routing-operator/pkg/controller/keyvault"
39
        "github.com/Azure/aks-app-routing-operator/pkg/controller/osm"
40
)
41

42
var scheme = runtime.NewScheme()
43

44
const (
45
        nicIngressClassIndex = "spec.ingressClassName"
46
)
47

48
func init() {
2✔
49
        registerSchemes(scheme)
2✔
50
        ctrl.SetLogger(getLogger())
2✔
51
        // need to set klog logger to same logger to get consistent logging format for all logs.
2✔
52
        // without this things like leader election that use klog will not have the same format.
2✔
53
        // https://github.com/kubernetes/client-go/blob/560efb3b8995da3adcec09865ca78c1ddc917cc9/tools/leaderelection/leaderelection.go#L250
2✔
54
        klog.SetLogger(getLogger())
2✔
55
}
2✔
56

57
func getLogger(opts ...zap.Opts) logr.Logger {
6✔
58
        // use raw opts to add caller info to logs
6✔
59
        rawOpts := zap.RawZapOpts(ubzap.AddCaller())
6✔
60

6✔
61
        // zap is the default recommended logger for controller-runtime when wanting json structured output
6✔
62
        return zap.New(append(opts, rawOpts)...)
6✔
63
}
6✔
64

65
func registerSchemes(s *runtime.Scheme) {
2✔
66
        utilruntime.Must(clientgoscheme.AddToScheme(s))
2✔
67
        utilruntime.Must(secv1.Install(s))
2✔
68
        utilruntime.Must(cfgv1alpha2.AddToScheme(s))
2✔
69
        utilruntime.Must(policyv1alpha1.AddToScheme(s))
2✔
70
        utilruntime.Must(approutingv1alpha1.AddToScheme(s))
2✔
71
        utilruntime.Must(apiextensionsv1.AddToScheme(s))
2✔
72
}
2✔
73

UNCOV
74
func NewRestConfig(conf *config.Config) *rest.Config {
×
UNCOV
75
        rc := ctrl.GetConfigOrDie()
×
UNCOV
76
        if conf.ServiceAccountTokenPath != "" {
×
77
                rc.BearerTokenFile = conf.ServiceAccountTokenPath
×
78
        }
×
79

80
        return rc
×
81
}
82

83
func NewManagerForRestConfig(conf *config.Config, rc *rest.Config) (ctrl.Manager, error) {
×
UNCOV
84
        m, err := ctrl.NewManager(rc, ctrl.Options{
×
UNCOV
85
                Metrics:                metricsserver.Options{BindAddress: conf.MetricsAddr},
×
86
                HealthProbeBindAddress: conf.ProbeAddr,
×
87
                Scheme:                 scheme,
×
88

×
89
                // we use an active-passive HA model meaning only the leader performs actions
×
90
                LeaderElection:          true,
×
91
                LeaderElectionNamespace: "kube-system",
×
92
                LeaderElectionID:        "aks-app-routing-operator-leader",
×
93
        })
×
94
        if err != nil {
×
95
                return nil, fmt.Errorf("creating manager: %w", err)
×
96
        }
×
97

98
        setupLog := m.GetLogger().WithName("setup")
×
99
        if err := setupProbes(conf, m, setupLog); err != nil {
×
UNCOV
100
                setupLog.Error(err, "failed to set up probes")
×
101
                return nil, fmt.Errorf("setting up probes: %w", err)
×
102
        }
×
103

104
        // create non-caching clients, non-caching for use before manager has started
105
        cl, err := client.New(rc, client.Options{Scheme: scheme})
×
UNCOV
106
        if err != nil {
×
UNCOV
107
                setupLog.Error(err, "unable to create non-caching client")
×
108
                return nil, fmt.Errorf("creating non-caching client: %w", err)
×
109
        }
×
110

111
        if err := loadCRDs(cl, conf, setupLog); err != nil {
×
112
                setupLog.Error(err, "failed to load CRDs")
×
UNCOV
113
                return nil, fmt.Errorf("loading CRDs: %w", err)
×
114
        }
×
115

116
        if err := setupIndexers(m, setupLog); err != nil {
×
117
                setupLog.Error(err, "unable to setup indexers")
×
UNCOV
118
                return nil, fmt.Errorf("setting up indexers: %w", err)
×
119
        }
×
120

121
        if err := setupControllers(m, conf, setupLog, cl); err != nil {
×
122
                setupLog.Error(err, "unable to setup controllers")
×
UNCOV
123
                return nil, fmt.Errorf("setting up controllers: %w", err)
×
124
        }
×
125

126
        return m, nil
×
127
}
128

129
func setupIndexers(mgr ctrl.Manager, lgr logr.Logger) error {
×
UNCOV
130
        lgr.Info("setting up indexers")
×
UNCOV
131

×
132
        lgr.Info("adding Nginx Ingress Controller IngressClass indexer")
×
133
        if err := nginxingress.AddIngressClassNameIndex(mgr.GetFieldIndexer(), nicIngressClassIndex); err != nil {
×
134
                lgr.Error(err, "adding Nginx Ingress Controller IngressClass indexer")
×
135
                return fmt.Errorf("adding Nginx Ingress Controller IngressClass indexer: %w", err)
×
136
        }
×
137

138
        lgr.Info("finished setting up indexers")
×
139
        return nil
×
140
}
141

142
func setupControllers(mgr ctrl.Manager, conf *config.Config, lgr logr.Logger, cl client.Client) error {
×
143
        lgr.Info("setting up controllers")
×
144

×
145
        lgr.Info("determining default IngressClass controller class")
×
UNCOV
146
        defaultCc, err := nginxingress.GetDefaultIngressClassControllerClass(cl)
×
UNCOV
147
        if err != nil {
×
148
                return fmt.Errorf("determining default IngressClass controller class: %w", err)
×
149
        }
×
150

UNCOV
151
        lgr.Info("settup up ExternalDNS controller")
×
152
        if err := dns.NewExternalDns(mgr, conf); err != nil {
×
153
                return fmt.Errorf("setting up external dns controller: %w", err)
×
154
        }
×
155

156
        lgr.Info("setting up Nginx Ingress Controller reconciler")
×
157
        if err := nginxingress.NewReconciler(conf, mgr, defaultCc); err != nil {
×
158
                return fmt.Errorf("setting up nginx ingress controller reconciler: %w", err)
×
159
        }
×
160

161
        lgr.Info("setting up ingress cert config reconciler")
×
162
        if err = osm.NewIngressCertConfigReconciler(mgr, conf); err != nil {
×
163
                return fmt.Errorf("setting up ingress cert config reconciler: %w", err)
×
164
        }
×
165

166
        defaultNic := nginxingress.GetDefaultNginxIngressController()
×
167
        if err := service.NewNginxIngressReconciler(mgr, nginxingress.ToNginxIngressConfig(&defaultNic, defaultCc)); err != nil {
×
168
                return fmt.Errorf("setting up nginx ingress reconciler: %w", err)
×
169
        }
×
170

171
        lgr.Info("setting up default Nginx Ingress Controller reconciler")
×
172
        if err := nginxingress.NewDefaultReconciler(mgr, conf); err != nil {
×
173
                return fmt.Errorf("setting up nginx ingress default controller reconciler: %w", err)
×
174
        }
×
175

176
        lgr.Info("setting up ingress concurrency watchdog")
×
177
        if err := ingress.NewConcurrencyWatchdog(mgr, conf, ingress.GetListNginxWatchdogTargets(mgr.GetClient(), defaultCc)); err != nil {
×
178
                return fmt.Errorf("setting up ingress concurrency watchdog: %w", err)
×
179
        }
×
180

181
        ingressManager := keyvault.NewIngressManagerFromFn(func(ing *netv1.Ingress) (bool, error) {
×
182
                return nginxingress.IsIngressManaged(context.Background(), mgr.GetClient(), ing, nicIngressClassIndex)
×
183
        })
×
184
        lgr.Info("setting up keyvault secret provider class reconciler")
×
UNCOV
185
        if err := keyvault.NewIngressSecretProviderClassReconciler(mgr, conf, ingressManager); err != nil {
×
186
                return fmt.Errorf("setting up ingress secret provider class reconciler: %w", err)
×
187
        }
×
188
        lgr.Info("setting up nginx keyvault secret provider class reconciler")
×
189
        if err := keyvault.NewNginxSecretProviderClassReconciler(mgr, conf); err != nil {
×
UNCOV
190
                return fmt.Errorf("setting up nginx secret provider class reconciler: %w", err)
×
191
        }
×
192
        lgr.Info("setting up keyvault placeholder pod controller")
×
193
        if err := keyvault.NewPlaceholderPodController(mgr, conf, ingressManager); err != nil {
×
194
                return fmt.Errorf("setting up placeholder pod controller: %w", err)
×
195
        }
×
196
        lgr.Info("setting up ingress tls reconciler")
×
197
        if err := keyvault.NewIngressTlsReconciler(mgr, conf, ingressManager); err != nil {
×
198
                return fmt.Errorf("setting up ingress tls reconciler: %w", err)
×
199
        }
×
200
        lgr.Info("setting up keyvault event mirror")
×
201
        if err = keyvault.NewEventMirror(mgr, conf); err != nil {
×
202
                return fmt.Errorf("setting up event mirror: %w", err)
×
203
        }
×
204

205
        ingressSourceSpecer := osm.NewIngressControllerSourceSpecerFromFn(func(ing *netv1.Ingress) (policyv1alpha1.IngressSourceSpec, bool, error) {
×
206
                return nginxingress.IngressSource(context.Background(), mgr.GetClient(), conf, defaultCc, ing, nicIngressClassIndex)
×
207
        })
×
208
        lgr.Info("setting up ingress backend reconciler")
×
209
        if err := osm.NewIngressBackendReconciler(mgr, conf, ingressSourceSpecer); err != nil {
×
210
                return fmt.Errorf("setting up ingress backend reconciler: %w", err)
×
211
        }
×
212

213
        lgr.Info("finished setting up controllers")
×
UNCOV
214
        return nil
×
215
}
216

217
func setupProbes(conf *config.Config, mgr ctrl.Manager, log logr.Logger) error {
×
218
        log.Info("adding probes to manager")
×
219

×
220
        check := func(req *http.Request) error { return nil }
×
221

UNCOV
222
        if err := mgr.AddReadyzCheck("readyz", check); err != nil {
×
223
                return fmt.Errorf("adding readyz check: %w", err)
×
224
        }
×
225

226
        if err := mgr.AddHealthzCheck("healthz", check); err != nil {
×
227
                return fmt.Errorf("adding healthz check: %w", err)
×
UNCOV
228
        }
×
229

230
        log.Info("added probes to manager")
×
231
        return nil
×
232
}
233

234
func getSelfDeploy(kcs kubernetes.Interface, conf *config.Config, log logr.Logger) (*appsv1.Deployment, error) {
4✔
235
        // this doesn't actually work today. operator ns is not the same as resource ns which means we can't set this operator
4✔
236
        // as the owner of any child resources. https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/#owner-references-in-object-specifications
4✔
237
        // dynamic provisioning through a crd will fix this and fix our garbage collection.
4✔
238

4✔
239
        deploy, err := kcs.AppsV1().Deployments(conf.NS).Get(context.Background(), conf.OperatorDeployment, metav1.GetOptions{})
4✔
240
        if errors.IsNotFound(err) {
6✔
241
                // It's okay if we don't find the deployment - just skip setting ownership references latter
2✔
242
                log.Info("self deploy not found")
2✔
243
                return nil, nil
2✔
244
        }
2✔
245
        if err != nil {
2✔
UNCOV
246
                return nil, err
×
247
        }
×
248
        return deploy, nil
2✔
249
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc