Add/update/delete PrometheusRemoteEndpoint CR
[demo.git] / vnfs / DAaaS / microservices / remote-config-operator / cmd / manager / main.go
1 package main
2
3 import (
4         "context"
5         "flag"
6         "fmt"
7         "os"
8         "runtime"
9
10         // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
11         _ "k8s.io/client-go/plugin/pkg/client/auth"
12         "k8s.io/client-go/rest"
13
14         "remote-config-operator/pkg/apis"
15         "remote-config-operator/pkg/controller"
16
17         monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
18         "github.com/operator-framework/operator-sdk/pkg/k8sutil"
19         kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics"
20         "github.com/operator-framework/operator-sdk/pkg/leader"
21         "github.com/operator-framework/operator-sdk/pkg/log/zap"
22         "github.com/operator-framework/operator-sdk/pkg/metrics"
23         "github.com/operator-framework/operator-sdk/pkg/restmapper"
24         sdkVersion "github.com/operator-framework/operator-sdk/version"
25         "github.com/spf13/pflag"
26         v1 "k8s.io/api/core/v1"
27         "k8s.io/apimachinery/pkg/util/intstr"
28         "sigs.k8s.io/controller-runtime/pkg/client/config"
29         logf "sigs.k8s.io/controller-runtime/pkg/log"
30         "sigs.k8s.io/controller-runtime/pkg/manager"
31         "sigs.k8s.io/controller-runtime/pkg/manager/signals"
32 )
33
34 // Change below variables to serve metrics on different host or port.
35 var (
36         metricsHost               = "0.0.0.0"
37         metricsPort         int32 = 8383
38         operatorMetricsPort int32 = 8686
39 )
40 var log = logf.Log.WithName("cmd")
41
42 func printVersion() {
43         log.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
44         log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
45         log.Info(fmt.Sprintf("Version of operator-sdk: %v", sdkVersion.Version))
46 }
47
48 func main() {
49         // Add the zap logger flag set to the CLI. The flag set must
50         // be added before calling pflag.Parse().
51         pflag.CommandLine.AddFlagSet(zap.FlagSet())
52
53         // Add flags registered by imported packages (e.g. glog and
54         // controller-runtime)
55         pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
56
57         pflag.Parse()
58
59         // Use a zap logr.Logger implementation. If none of the zap
60         // flags are configured (or if the zap flag set is not being
61         // used), this defaults to a production zap logger.
62         //
63         // The logger instantiated here can be changed to any logger
64         // implementing the logr.Logger interface. This logger will
65         // be propagated through the whole operator, generating
66         // uniform and structured logs.
67         logf.SetLogger(zap.Logger())
68
69         printVersion()
70
71         namespace, err := k8sutil.GetWatchNamespace()
72         if err != nil {
73                 log.Error(err, "Failed to get watch namespace")
74                 os.Exit(1)
75         }
76
77         // Get a config to talk to the apiserver
78         cfg, err := config.GetConfig()
79         if err != nil {
80                 log.Error(err, "")
81                 os.Exit(1)
82         }
83
84         ctx := context.TODO()
85         // Become the leader before proceeding
86         err = leader.Become(ctx, "remote-config-operator-lock")
87         if err != nil {
88                 log.Error(err, "")
89                 os.Exit(1)
90         }
91
92         // Create a new Cmd to provide shared dependencies and start components
93         mgr, err := manager.New(cfg, manager.Options{
94                 Namespace:          namespace,
95                 MapperProvider:     restmapper.NewDynamicRESTMapper,
96                 MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
97         })
98         if err != nil {
99                 log.Error(err, "")
100                 os.Exit(1)
101         }
102
103         log.Info("Registering Components.")
104
105         // Setup Scheme for all resources
106         if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
107                 log.Error(err, "")
108                 os.Exit(1)
109         }
110
111         // Adding the monitoringv1
112         if err := monitoringv1.AddToScheme(mgr.GetScheme()); err != nil {
113                 log.Error(err, "")
114                 os.Exit(1)
115         }
116
117         // Setup all Controllers
118         if err := controller.AddToManager(mgr); err != nil {
119                 log.Error(err, "")
120                 os.Exit(1)
121         }
122
123         if err = serveCRMetrics(cfg); err != nil {
124                 log.Info("Could not generate and serve custom resource metrics", "error", err.Error())
125         }
126
127         // Add to the below struct any other metrics ports you want to expose.
128         servicePorts := []v1.ServicePort{
129                 {Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},
130                 {Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},
131         }
132         // Create Service object to expose the metrics port(s).
133         service, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)
134         if err != nil {
135                 log.Info("Could not create metrics Service", "error", err.Error())
136         }
137
138         // CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
139         // necessary to configure Prometheus to scrape metrics from this operator.
140         services := []*v1.Service{service}
141         _, err = metrics.CreateServiceMonitors(cfg, namespace, services)
142         if err != nil {
143                 log.Info("Could not create ServiceMonitor object", "error", err.Error())
144                 // If this operator is deployed to a cluster without the prometheus-operator running, it will return
145                 // ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.
146                 if err == metrics.ErrServiceMonitorNotPresent {
147                         log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error())
148                 }
149         }
150
151         log.Info("Starting the Cmd.")
152
153         // Start the Cmd
154         if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
155                 log.Error(err, "Manager exited non-zero")
156                 os.Exit(1)
157         }
158 }
159
160 // serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
161 // It serves those metrics on "http://metricsHost:operatorMetricsPort".
162 func serveCRMetrics(cfg *rest.Config) error {
163         // Below function returns filtered operator/CustomResource specific GVKs.
164         // For more control override the below GVK list with your own custom logic.
165         filteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)
166         if err != nil {
167                 return err
168         }
169         // Get the namespace the operator is currently deployed in.
170         operatorNs, err := k8sutil.GetOperatorNamespace()
171         if err != nil {
172                 return err
173         }
174         // To generate metrics in other namespaces, add the values below.
175         ns := []string{operatorNs}
176         // Generate and serve custom resource specific metrics.
177         err = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)
178         if err != nil {
179                 return err
180         }
181         return nil
182 }