Skip to content
This repository was archived by the owner on Nov 18, 2020. It is now read-only.

Commit 0d98e8c

Browse files
upgrade go sample to 0.16.0 (#116)
1 parent 0cc2191 commit 0d98e8c

5 files changed

Lines changed: 285 additions & 29 deletions

File tree

go/memcached-operator/cmd/manager/main.go

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package main
22

33
import (
44
"context"
5+
"errors"
56
"flag"
67
"fmt"
78
"os"
89
"runtime"
10+
"strings"
911

1012
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
1113
_ "k8s.io/client-go/plugin/pkg/client/auth"
@@ -24,7 +26,7 @@ import (
2426
"github.com/spf13/pflag"
2527
v1 "k8s.io/api/core/v1"
2628
"k8s.io/apimachinery/pkg/util/intstr"
27-
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
29+
"sigs.k8s.io/controller-runtime/pkg/cache"
2830
"sigs.k8s.io/controller-runtime/pkg/client/config"
2931
logf "sigs.k8s.io/controller-runtime/pkg/log"
3032
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -90,12 +92,23 @@ func main() {
9092
os.Exit(1)
9193
}
9294

93-
// Create a new Cmd to provide shared dependencies and start components
94-
mgr, err := manager.New(cfg, manager.Options{
95+
// Set default manager options
96+
options := manager.Options{
9597
Namespace: namespace,
96-
MapperProvider: apiutil.NewDiscoveryRESTMapper,
9798
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
98-
})
99+
}
100+
101+
// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)
102+
// Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate
103+
// Also note that you may face performance issues when using this with a high number of namespaces.
104+
// More Info: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
105+
if strings.Contains(namespace, ",") {
106+
options.Namespace = ""
107+
options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, ","))
108+
}
109+
110+
// Create a new manager to provide shared dependencies and start components
111+
mgr, err := manager.New(cfg, options)
99112
if err != nil {
100113
log.Error(err, "")
101114
os.Exit(1)
@@ -115,7 +128,31 @@ func main() {
115128
os.Exit(1)
116129
}
117130

118-
if err = serveCRMetrics(cfg); err != nil {
131+
// Add the Metrics Service
132+
addMetrics(ctx, cfg)
133+
134+
log.Info("Starting the Cmd.")
135+
136+
// Start the Cmd
137+
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
138+
log.Error(err, "Manager exited non-zero")
139+
os.Exit(1)
140+
}
141+
}
142+
143+
// addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using
144+
// the Prometheus operator
145+
func addMetrics(ctx context.Context, cfg *rest.Config) {
146+
// Get the namespace the operator is currently deployed in.
147+
operatorNs, err := k8sutil.GetOperatorNamespace()
148+
if err != nil {
149+
if errors.Is(err, k8sutil.ErrRunLocal) {
150+
log.Info("Skipping CR metrics server creation; not running in a cluster.")
151+
return
152+
}
153+
}
154+
155+
if err := serveCRMetrics(cfg, operatorNs); err != nil {
119156
log.Info("Could not generate and serve custom resource metrics", "error", err.Error())
120157
}
121158

@@ -124,6 +161,7 @@ func main() {
124161
{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},
125162
{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},
126163
}
164+
127165
// Create Service object to expose the metrics port(s).
128166
service, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)
129167
if err != nil {
@@ -133,7 +171,9 @@ func main() {
133171
// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
134172
// necessary to configure Prometheus to scrape metrics from this operator.
135173
services := []*v1.Service{service}
136-
_, err = metrics.CreateServiceMonitors(cfg, namespace, services)
174+
175+
// The ServiceMonitor is created in the same namespace where the operator is deployed
176+
_, err = metrics.CreateServiceMonitors(cfg, operatorNs, services)
137177
if err != nil {
138178
log.Info("Could not create ServiceMonitor object", "error", err.Error())
139179
// If this operator is deployed to a cluster without the prometheus-operator running, it will return
@@ -142,32 +182,26 @@ func main() {
142182
log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error())
143183
}
144184
}
145-
146-
log.Info("Starting the Cmd.")
147-
148-
// Start the Cmd
149-
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
150-
log.Error(err, "Manager exited non-zero")
151-
os.Exit(1)
152-
}
153185
}
154186

155187
// serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
156188
// It serves those metrics on "http://metricsHost:operatorMetricsPort".
157-
func serveCRMetrics(cfg *rest.Config) error {
158-
// Below function returns filtered operator/CustomResource specific GVKs.
159-
// For more control override the below GVK list with your own custom logic.
189+
func serveCRMetrics(cfg *rest.Config, operatorNs string) error {
190+
// The function below returns a list of filtered operator/CR specific GVKs. For more control, override the GVK list below
191+
// with your own custom logic. Note that if you are adding third party API schemas, probably you will need to
192+
// customize this implementation to avoid permissions issues.
160193
filteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)
161194
if err != nil {
162195
return err
163196
}
164-
// Get the namespace the operator is currently deployed in.
165-
operatorNs, err := k8sutil.GetOperatorNamespace()
197+
198+
// The metrics will be generated from the namespaces which are returned here.
199+
// NOTE that passing nil or an empty list of namespaces in GenerateAndServeCRMetrics will result in an error.
200+
ns, err := kubemetrics.GetNamespacesForMetrics(operatorNs)
166201
if err != nil {
167202
return err
168203
}
169-
// To generate metrics in other namespaces, add the values below.
170-
ns := []string{operatorNs}
204+
171205
// Generate and serve custom resource specific metrics.
172206
err = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)
173207
if err != nil {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: memcacheds.cache.example.com
5+
spec:
6+
group: cache.example.com
7+
names:
8+
kind: Memcached
9+
listKind: MemcachedList
10+
plural: memcacheds
11+
singular: memcached
12+
scope: Namespaced
13+
subresources:
14+
status: {}
15+
validation:
16+
openAPIV3Schema:
17+
description: Memcached is the Schema for the memcacheds API
18+
properties:
19+
apiVersion:
20+
description: 'APIVersion defines the versioned schema of this representation
21+
of an object. Servers should convert recognized schemas to the latest
22+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
23+
type: string
24+
kind:
25+
description: 'Kind is a string value representing the REST resource this
26+
object represents. Servers may infer this from the endpoint the client
27+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
28+
type: string
29+
metadata:
30+
type: object
31+
spec:
32+
description: MemcachedSpec defines the desired state of Memcached
33+
properties:
34+
size:
35+
description: Size is the size of the memcached deployment
36+
format: int32
37+
type: integer
38+
required:
39+
- size
40+
type: object
41+
status:
42+
description: MemcachedStatus defines the observed state of Memcached
43+
properties:
44+
nodes:
45+
description: Nodes are the names of the memcached pods
46+
items:
47+
type: string
48+
type: array
49+
required:
50+
- nodes
51+
type: object
52+
type: object
53+
version: v1alpha1
54+
versions:
55+
- name: v1alpha1
56+
served: true
57+
storage: true
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
apiVersion: operators.coreos.com/v1alpha1
2+
kind: ClusterServiceVersion
3+
metadata:
4+
annotations:
5+
alm-examples: |-
6+
[
7+
{
8+
"apiVersion": "cache.example.com/v1alpha1",
9+
"kind": "Memcached",
10+
"metadata": {
11+
"name": "example-memcached"
12+
},
13+
"spec": {
14+
"size": 3
15+
}
16+
}
17+
]
18+
capabilities: Basic Install
19+
name: memcached-operator.v0.16.0
20+
namespace: placeholder
21+
spec:
22+
apiservicedefinitions: {}
23+
customresourcedefinitions:
24+
owned:
25+
- description: Memcached is the Schema for the memcacheds API
26+
kind: Memcached
27+
name: memcacheds.cache.example.com
28+
version: v1alpha1
29+
description: Operator-SDK Go Memcached sample.
30+
displayName: Memcached Operator
31+
icon:
32+
- base64data: ""
33+
mediatype: ""
34+
install:
35+
spec:
36+
deployments:
37+
- name: memcached-operator
38+
spec:
39+
replicas: 1
40+
selector:
41+
matchLabels:
42+
name: memcached-operator
43+
strategy: {}
44+
template:
45+
metadata:
46+
labels:
47+
name: memcached-operator
48+
spec:
49+
containers:
50+
- command:
51+
- memcached-operator
52+
env:
53+
- name: WATCH_NAMESPACE
54+
valueFrom:
55+
fieldRef:
56+
fieldPath: metadata.annotations['olm.targetNamespaces']
57+
- name: POD_NAME
58+
valueFrom:
59+
fieldRef:
60+
fieldPath: metadata.name
61+
- name: OPERATOR_NAME
62+
value: memcached-operator
63+
image: REPLACE_IMAGE
64+
imagePullPolicy: Always
65+
name: memcached-operator
66+
resources: {}
67+
serviceAccountName: memcached-operator
68+
permissions:
69+
- rules:
70+
- apiGroups:
71+
- ""
72+
resources:
73+
- pods
74+
- services
75+
- services/finalizers
76+
- endpoints
77+
- persistentvolumeclaims
78+
- events
79+
- configmaps
80+
- secrets
81+
verbs:
82+
- create
83+
- delete
84+
- get
85+
- list
86+
- patch
87+
- update
88+
- watch
89+
- apiGroups:
90+
- apps
91+
resources:
92+
- deployments
93+
- daemonsets
94+
- replicasets
95+
- statefulsets
96+
verbs:
97+
- create
98+
- delete
99+
- get
100+
- list
101+
- patch
102+
- update
103+
- watch
104+
- apiGroups:
105+
- monitoring.coreos.com
106+
resources:
107+
- servicemonitors
108+
verbs:
109+
- get
110+
- create
111+
- apiGroups:
112+
- apps
113+
resourceNames:
114+
- memcached-operator
115+
resources:
116+
- deployments/finalizers
117+
verbs:
118+
- update
119+
- apiGroups:
120+
- ""
121+
resources:
122+
- pods
123+
verbs:
124+
- get
125+
- apiGroups:
126+
- apps
127+
resources:
128+
- replicasets
129+
- deployments
130+
verbs:
131+
- get
132+
- apiGroups:
133+
- cache.example.com
134+
resources:
135+
- '*'
136+
verbs:
137+
- create
138+
- delete
139+
- get
140+
- list
141+
- patch
142+
- update
143+
- watch
144+
serviceAccountName: memcached-operator
145+
strategy: deployment
146+
installModes:
147+
- supported: true
148+
type: OwnNamespace
149+
- supported: true
150+
type: SingleNamespace
151+
- supported: false
152+
type: MultiNamespace
153+
- supported: true
154+
type: AllNamespaces
155+
keywords:
156+
- memcached
157+
- app
158+
maintainers:
159+
- email: corp@example.com
160+
name: Some Corp
161+
maturity: alpha
162+
provider:
163+
name: Example
164+
url: www.example.com
165+
version: 0.16.0

go/memcached-operator/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.13
44

55
require (
66
github.com/go-openapi/spec v0.19.4
7-
github.com/operator-framework/operator-sdk v0.15.2
7+
github.com/operator-framework/operator-sdk v0.16.0
88
github.com/spf13/pflag v1.0.5
99
k8s.io/api v0.0.0
1010
k8s.io/apimachinery v0.0.0

0 commit comments

Comments
 (0)