Skip to content

Commit ddef3f5

Browse files
pkg/generator: Generate all manifests needed for Prometheus integration
1 parent 8aeaff3 commit ddef3f5

9 files changed

+194
-9
lines changed

Gopkg.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
name = "github.com/spf13/cobra"
77
version = "0.0.2"
88

9+
[[override]]
10+
name = "github.com/prometheus/client_golang"
11+
version = "0.8.0"
12+
913
[[override]]
1014
name = "k8s.io/api"
1115
version = "kubernetes-1.9.3"

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ $ kubectl create -f deploy/rbac.yaml
5656
$ kubectl create -f deploy/crd.yaml
5757
$ kubectl create -f deploy/operator.yaml
5858

59+
# Monitor the app-operator using prometheus and serviceMonitor CRD
60+
$ kubectl create -f deploy/service.yaml
61+
$ kubectl create -f deploy/serviceMonitor.yaml
62+
5963
# By default, creating a custom resource (App) triggers the app-operator to deploy a busybox pod
6064
$ kubectl create -f deploy/cr.yaml
6165

@@ -68,6 +72,8 @@ busy-box 1/1 Running 0 50s
6872
$ kubectl delete -f deploy/cr.yaml
6973
$ kubectl delete -f deploy/operator.yaml
7074
$ kubectl delete -f deploy/rbac.yaml
75+
$ kubectl delete -f deploy/service.yaml
76+
$ kubectl delete -f deploy.serviceMonitor.yaml
7177
```
7278

7379
To learn more about the operator-sdk, see the [user guide][guide].

pkg/generator/deploy_tmpl.go

+33-2
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,23 @@ const operatorYamlTmpl = `apiVersion: apps/v1
3333
kind: Deployment
3434
metadata:
3535
name: {{.ProjectName}}
36+
labels:
37+
k8s-app: {{.ProjectName}}
3638
spec:
3739
replicas: 1
3840
selector:
3941
matchLabels:
40-
name: {{.ProjectName}}
42+
k8s-app: {{.ProjectName}}
4143
template:
4244
metadata:
4345
labels:
44-
name: {{.ProjectName}}
46+
k8s-app: {{.ProjectName}}
4547
spec:
4648
containers:
4749
- name: {{.ProjectName}}
4850
image: {{.Image}}
51+
ports:
52+
- containerPort: 9090
4953
command:
5054
- {{.ProjectName}}
5155
imagePullPolicy: Always
@@ -109,3 +113,30 @@ kind: "{{.Kind}}"
109113
metadata:
110114
name: "example"
111115
`
116+
117+
const serviceYamlTmpl = `apiVersion: v1
118+
kind: Service
119+
metadata:
120+
name: {{.ProjectName}}
121+
labels:
122+
k8s-app: {{.ProjectName}}
123+
spec:
124+
selector:
125+
k8s-app: {{.ProjectName}}
126+
ports:
127+
- protocol: TCP
128+
port: 9090
129+
name: "metrics"`
130+
131+
const serviceMonitorYamlTmpl = `apiVersion: monitoring.coreos.com/v1
132+
kind: ServiceMonitor
133+
metadata:
134+
name: {{.ProjectName}}
135+
labels:
136+
k8s-app: {{.ProjectName}}
137+
spec:
138+
selector:
139+
matchLabels:
140+
k8s-app: {{.ProjectName}}
141+
endpoints:
142+
- port: metrics`

pkg/generator/gen_deploy.go

+47-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import (
2222
)
2323

2424
const (
25-
crdTmplName = "deploy/crd.yaml"
26-
operatorTmplName = "deploy/operator.yaml"
27-
rbacTmplName = "deploy/rbac.yaml"
28-
crTmplName = "deploy/cr.yaml"
25+
crdTmplName = "deploy/crd.yaml"
26+
operatorTmplName = "deploy/operator.yaml"
27+
rbacTmplName = "deploy/rbac.yaml"
28+
crTmplName = "deploy/cr.yaml"
29+
serviceTmplName = "deploy/service.yaml"
30+
serviceMonitorTmplName = "deploy/serviceMonitor.yaml"
2931
)
3032

3133
// CRDYaml contains data needed to generate deploy/crd.yaml
@@ -77,6 +79,47 @@ func renderOperatorYaml(w io.Writer, projectName, image string) error {
7779
return t.Execute(w, o)
7880
}
7981

82+
// ServiceYaml contains all the customized data needed to generate deploy/service.yaml for a new operator
83+
// This service will be monitor by prometheus
84+
// when pairing with serviceYamlTmpl template.
85+
type ServiceYaml struct {
86+
ProjectName string
87+
}
88+
89+
// renderServiceYaml generates deploy/service.yaml.
90+
func renderServiceYaml(w io.Writer, projectName string) error {
91+
t := template.New(serviceTmplName)
92+
t, err := t.Parse(serviceYamlTmpl)
93+
if err != nil {
94+
return fmt.Errorf("Failed to parse service yaml template: %v", err)
95+
}
96+
97+
s := ServiceYaml{
98+
ProjectName: projectName,
99+
}
100+
return t.Execute(w, s)
101+
}
102+
103+
// ServiceMonitorYaml contains all the customized data needed to generate deploy/serviceMonitor.yaml for a new operator
104+
// when pairing with serviceMonitorYamlTmpl template.
105+
type ServiceMonitorYaml struct {
106+
ProjectName string
107+
}
108+
109+
// renderServiceYaml generates deploy/service.yaml.
110+
func renderServiceMonitorYaml(w io.Writer, projectName string) error {
111+
t := template.New(serviceMonitorTmplName)
112+
t, err := t.Parse(serviceMonitorYamlTmpl)
113+
if err != nil {
114+
return fmt.Errorf("Failed to parse serviceMonitor yaml template: %v", err)
115+
}
116+
117+
s := ServiceYaml{
118+
ProjectName: projectName,
119+
}
120+
return t.Execute(w, s)
121+
}
122+
80123
// RBACYaml contains all the customized data needed to generate deploy/rbac.yaml for a new operator
81124
// when pairing with rbacYamlTmpl template.
82125
type RBACYaml struct {

pkg/generator/gen_deploy_test.go

+49-2
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,23 @@ const operatorYamlExp = `apiVersion: apps/v1
2424
kind: Deployment
2525
metadata:
2626
name: app-operator
27+
labels:
28+
k8s-app: app-operator
2729
spec:
2830
replicas: 1
2931
selector:
3032
matchLabels:
31-
name: app-operator
33+
k8s-app: app-operator
3234
template:
3335
metadata:
3436
labels:
35-
name: app-operator
37+
k8s-app: app-operator
3638
spec:
3739
containers:
3840
- name: app-operator
3941
image: quay.io/example-inc/app-operator:0.0.1
42+
ports:
43+
- containerPort: 9090
4044
command:
4145
- app-operator
4246
imagePullPolicy: Always
@@ -95,6 +99,33 @@ roleRef:
9599
apiGroup: rbac.authorization.k8s.io
96100
`
97101

102+
const serviceYamlExp = `apiVersion: v1
103+
kind: Service
104+
metadata:
105+
name: app-operator
106+
labels:
107+
k8s-app: app-operator
108+
spec:
109+
selector:
110+
k8s-app: app-operator
111+
ports:
112+
- protocol: TCP
113+
port: 9090
114+
name: "metrics"`
115+
116+
const serviceMonitorYamlExp = `apiVersion: monitoring.coreos.com/v1
117+
kind: ServiceMonitor
118+
metadata:
119+
name: app-operator
120+
labels:
121+
k8s-app: app-operator
122+
spec:
123+
selector:
124+
matchLabels:
125+
k8s-app: app-operator
126+
endpoints:
127+
- port: metrics`
128+
98129
func TestGenDeploy(t *testing.T) {
99130
buf := &bytes.Buffer{}
100131
if err := renderCRDYaml(buf, appKind, appAPIVersion); err != nil {
@@ -119,4 +150,20 @@ func TestGenDeploy(t *testing.T) {
119150
if rbacYamlExp != buf.String() {
120151
t.Errorf("want %v, got %v", rbacYamlExp, buf.String())
121152
}
153+
154+
buf = &bytes.Buffer{}
155+
if err := renderServiceYaml(buf, appProjectName); err != nil {
156+
t.Error(err)
157+
}
158+
if serviceYamlExp != buf.String() {
159+
t.Errorf("want %v, got %v", serviceYamlExp, buf.String())
160+
}
161+
162+
buf = &bytes.Buffer{}
163+
if err := renderServiceMonitorYaml(buf, appProjectName); err != nil {
164+
t.Error(err)
165+
}
166+
if serviceMonitorYamlExp != buf.String() {
167+
t.Errorf("want %v, got %v", serviceMonitorYamlExp, buf.String())
168+
}
122169
}

pkg/generator/generator.go

+36
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ const (
5454
gopkglock = "Gopkg.lock"
5555
config = "config.yaml"
5656
operatorYaml = deployDir + "/operator.yaml"
57+
serviceYaml = "service.yaml"
58+
serviceMonitorYaml = "serviceMonitor.yaml"
5759
rbacYaml = "rbac.yaml"
5860
crYaml = "cr.yaml"
5961
catalogPackageYaml = "package.yaml"
@@ -206,6 +208,22 @@ func renderDeployFiles(deployDir, projectName, apiVersion, kind string) error {
206208
return err
207209
}
208210

211+
buf = &bytes.Buffer{}
212+
if err := renderServiceYaml(buf, projectName); err != nil {
213+
return err
214+
}
215+
if err := writeFileAndPrint(filepath.Join(deployDir, serviceYaml), buf.Bytes(), defaultFileMode); err != nil {
216+
return err
217+
}
218+
219+
buf = &bytes.Buffer{}
220+
if err := renderServiceMonitorYaml(buf, projectName); err != nil {
221+
return err
222+
}
223+
if err := writeFileAndPrint(filepath.Join(deployDir, serviceMonitorYaml), buf.Bytes(), defaultFileMode); err != nil {
224+
return err
225+
}
226+
209227
buf = &bytes.Buffer{}
210228
if err := renderCRDYaml(buf, kind, apiVersion); err != nil {
211229
return err
@@ -230,6 +248,24 @@ func RenderOperatorYaml(c *Config, image string) error {
230248
return ioutil.WriteFile(operatorYaml, buf.Bytes(), defaultFileMode)
231249
}
232250

251+
// RenderServiceYaml generates "deploy/service.yaml"
252+
func RenderServiceYaml(c *Config) error {
253+
buf := &bytes.Buffer{}
254+
if err := renderServiceYaml(buf, c.ProjectName); err != nil {
255+
return err
256+
}
257+
return ioutil.WriteFile(serviceYaml, buf.Bytes(), defaultFileMode)
258+
}
259+
260+
// RenderServiceMonitorYaml generates "deploy/serviceMonitor.yaml"
261+
func RenderServiceMonitorYaml(c *Config) error {
262+
buf := &bytes.Buffer{}
263+
if err := renderServiceMonitorYaml(buf, c.ProjectName); err != nil {
264+
return err
265+
}
266+
return ioutil.WriteFile(serviceMonitorYaml, buf.Bytes(), defaultFileMode)
267+
}
268+
233269
// RenderOlmCatalog generates catalog manifests "deploy/olm-catalog/*"
234270
// The current working directory must be the project repository root
235271
func RenderOlmCatalog(c *Config, image, version string) error {

pkg/generator/generator_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,33 @@ const mainExp = `package main
2424
import (
2525
"context"
2626
"runtime"
27+
"net/http"
2728
2829
stub "github.com/example-inc/app-operator/pkg/stub"
2930
sdk "github.com/operator-framework/operator-sdk/pkg/sdk"
3031
k8sutil "github.com/operator-framework/operator-sdk/pkg/util/k8sutil"
3132
sdkVersion "github.com/operator-framework/operator-sdk/version"
3233
34+
"github.com/prometheus/client_golang/prometheus/promhttp"
3335
"github.com/sirupsen/logrus"
3436
)
3537
38+
// Prometheus metrics port
39+
const promPort = ":9090"
40+
3641
func printVersion() {
3742
logrus.Infof("Go Version: %s", runtime.Version())
3843
logrus.Infof("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)
3944
logrus.Infof("operator-sdk Version: %v", sdkVersion.Version)
45+
logrus.Infof("operator prometheus port :%s", promPort)
4046
}
4147
4248
func main() {
4349
printVersion()
4450
51+
http.Handle("/metrics", promhttp.Handler())
52+
logrus.Fatalf("%s", http.ListenAndServe(promPort, nil))
53+
4554
resource := "app.example.com/v1alpha1"
4655
kind := "AppService"
4756
namespace, err := k8sutil.GetWatchNamespace()

pkg/generator/main_tmpl.go

+9
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,33 @@ const mainTmpl = `package main
2020
import (
2121
"context"
2222
"runtime"
23+
"net/http"
2324
2425
stub "{{.StubImport}}"
2526
sdk "{{.OperatorSDKImport}}"
2627
k8sutil "{{.K8sutilImport}}"
2728
sdkVersion "{{.SDKVersionImport}}"
2829
30+
"github.com/prometheus/client_golang/prometheus/promhttp"
2931
"github.com/sirupsen/logrus"
3032
)
3133
34+
// Prometheus metrics port
35+
const promPort = ":9090"
36+
3237
func printVersion() {
3338
logrus.Infof("Go Version: %s", runtime.Version())
3439
logrus.Infof("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)
3540
logrus.Infof("operator-sdk Version: %v", sdkVersion.Version)
41+
logrus.Infof("operator prometheus port :%s", promPort)
3642
}
3743
3844
func main() {
3945
printVersion()
4046
47+
http.Handle("/metrics", promhttp.Handler())
48+
logrus.Fatalf("%s", http.ListenAndServe(promPort, nil))
49+
4150
resource := "{{.APIVersion}}"
4251
kind := "{{.Kind}}"
4352
namespace, err := k8sutil.GetWatchNamespace()

0 commit comments

Comments
 (0)