Skip to content

Commit d010976

Browse files
committed
feat: implement mvp controller
Signed-off-by: Bence Csati <[email protected]>
1 parent 4b0d848 commit d010976

File tree

10 files changed

+577
-14
lines changed

10 files changed

+577
-14
lines changed

charts/logging-operator/charts/logging-operator-crds/templates/logging.banzaicloud.io_axosyslogs.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ spec:
3636
type: object
3737
spec:
3838
properties:
39+
configReloadImage:
40+
properties:
41+
repository:
42+
type: string
43+
tag:
44+
type: string
45+
type: object
3946
destinations:
4047
items:
4148
properties:
@@ -45,6 +52,13 @@ spec:
4552
type: string
4653
type: object
4754
type: array
55+
image:
56+
properties:
57+
repository:
58+
type: string
59+
tag:
60+
type: string
61+
type: object
4862
logPaths:
4963
items:
5064
properties:

charts/logging-operator/crds/logging.banzaicloud.io_axosyslogs.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ spec:
3333
type: object
3434
spec:
3535
properties:
36+
configReloadImage:
37+
properties:
38+
repository:
39+
type: string
40+
tag:
41+
type: string
42+
type: object
3643
destinations:
3744
items:
3845
properties:
@@ -42,6 +49,13 @@ spec:
4249
type: string
4350
type: object
4451
type: array
52+
image:
53+
properties:
54+
repository:
55+
type: string
56+
tag:
57+
type: string
58+
type: object
4559
logPaths:
4660
items:
4761
properties:

config/crd/bases/logging.banzaicloud.io_axosyslogs.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ spec:
3333
type: object
3434
spec:
3535
properties:
36+
configReloadImage:
37+
properties:
38+
repository:
39+
type: string
40+
tag:
41+
type: string
42+
type: object
3643
destinations:
3744
items:
3845
properties:
@@ -42,6 +49,13 @@ spec:
4249
type: string
4350
type: object
4451
type: array
52+
image:
53+
properties:
54+
repository:
55+
type: string
56+
tag:
57+
type: string
58+
type: object
4559
logPaths:
4660
items:
4761
properties:

controllers/logging/axosyslog_controller.go

Lines changed: 137 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,34 @@ package controllers
1616

1717
import (
1818
"context"
19+
"fmt"
20+
"reflect"
21+
"runtime"
1922

23+
"emperror.dev/errors"
24+
"github.com/cisco-open/operator-tools/pkg/reconciler"
2025
"github.com/go-logr/logr"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2127
ctrl "sigs.k8s.io/controller-runtime"
2228
"sigs.k8s.io/controller-runtime/pkg/client"
2329

24-
"github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1"
30+
"github.com/kube-logging/logging-operator/pkg/resources"
31+
axosyslogresources "github.com/kube-logging/logging-operator/pkg/resources/axosyslog"
32+
v1beta1 "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1"
2533
)
2634

2735
// NewAxoSyslogReconciler creates a new AxoSyslogReconciler instance
28-
func NewAxoSyslogReconciler(client client.Client, log logr.Logger) *AxoSyslogReconciler {
36+
func NewAxoSyslogReconciler(client client.Client, log logr.Logger, opts reconciler.ReconcilerOpts) *AxoSyslogReconciler {
2937
return &AxoSyslogReconciler{
30-
Client: client,
31-
Log: log,
38+
Client: client,
39+
GenericResourceReconciler: reconciler.NewGenericReconciler(client, log, opts),
40+
Log: log,
3241
}
3342
}
3443

3544
type AxoSyslogReconciler struct {
3645
client.Client
46+
*reconciler.GenericResourceReconciler
3747
Log logr.Logger
3848
}
3949

@@ -42,29 +52,142 @@ type AxoSyslogReconciler struct {
4252
// +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete
4353
// +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete
4454
// +kubebuilder:rbac:groups="",resources=services;persistentvolumeclaims;serviceaccounts;pods,verbs=get;list;watch;create;update;patch;delete
45-
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=clusterroles;clusterrolebindings;roles;rolebindings,verbs=get;list;watch;create;update;patch;delete
55+
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles;rolebindings,verbs=get;list;watch;create;update;patch;delete
4656

47-
// Reconciles axosyslog resource
57+
// Reconcile implements the reconciliation logic for AxoSyslog resources
4858
func (r *AxoSyslogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
49-
log := r.Log.WithValues("axosyslog", req.NamespacedName)
59+
r.Log.V(1).Info("Reconciling AxoSyslog")
5060

51-
log.V(1).Info("Reconciling AxoSyslog")
52-
53-
var axosyslog v1beta1.AxoSyslog
54-
if err := r.Get(ctx, req.NamespacedName, &axosyslog); err != nil {
61+
var axoSyslog v1beta1.AxoSyslog
62+
if err := r.Get(ctx, req.NamespacedName, &axoSyslog); err != nil {
5563
return ctrl.Result{}, client.IgnoreNotFound(err)
5664
}
5765

58-
if err := axosyslog.SetDefaults(); err != nil {
66+
log := r.Log.WithValues("axosyslog", fmt.Sprintf("%s/%s", axoSyslog.Namespace, axoSyslog.Name))
67+
68+
if err := axoSyslog.SetDefaults(); err != nil {
69+
return ctrl.Result{}, errors.WrapIf(err, "failed to set defaults")
70+
}
71+
72+
if result, err := r.reconcileRBACResources(log, &axoSyslog); err != nil {
73+
return ctrl.Result{}, err
74+
} else if result != nil {
75+
return *result, nil
76+
}
77+
78+
// TODO: config-check ?
79+
// TODO: output-secret && secret-mark ?
80+
// TODO: config-secret?
81+
82+
if result, err := r.reconcileWorkloadResources(log, &axoSyslog); err != nil {
5983
return ctrl.Result{}, err
84+
} else if result != nil {
85+
return *result, nil
6086
}
6187

6288
return ctrl.Result{}, nil
6389
}
6490

91+
// reconcileRBACResources handles resources related to AxoSyslog
92+
func (r *AxoSyslogReconciler) reconcileRBACResources(log logr.Logger, axoSyslog *v1beta1.AxoSyslog) (*ctrl.Result, error) {
93+
resourceBuilders := []resources.ResourceWithNamespace{
94+
axosyslogresources.ServiceAccount,
95+
axosyslogresources.Role,
96+
axosyslogresources.RoleBinding,
97+
}
98+
99+
for _, buildObject := range resourceBuilders {
100+
builderName := getFunctionName(buildObject)
101+
log.V(2).Info("Processing resource", "builder", builderName)
102+
103+
o, state, err := buildObject(axoSyslog.Namespace)
104+
if err != nil {
105+
return nil, errors.WrapIff(err, "failed to build object with %s", builderName)
106+
}
107+
if o == nil {
108+
return nil, errors.Errorf("reconcile error: %s returned nil object", builderName)
109+
}
110+
111+
metaObj, ok := o.(metav1.Object)
112+
if !ok {
113+
return nil, errors.Errorf("reconcile error: %s returned non-metav1.Object", builderName)
114+
}
115+
116+
if metaObj.GetNamespace() == "" {
117+
return nil, errors.Errorf("reconcile error: %s returned resource without namespace set", builderName)
118+
}
119+
120+
if err := ctrl.SetControllerReference(axoSyslog, metaObj, r.Scheme()); err != nil {
121+
return nil, errors.WrapIff(err, "failed to set controller reference for %s", metaObj.GetName())
122+
}
123+
124+
result, err := r.ReconcileResource(o, state)
125+
if err != nil {
126+
return nil, errors.WrapIff(err, "failed to reconcile resource %s/%s", metaObj.GetNamespace(), metaObj.GetName())
127+
}
128+
if result != nil {
129+
return result, nil
130+
}
131+
}
132+
133+
return nil, nil
134+
}
135+
136+
// reconcileWorkloadResources handles resources related to AxoSyslog and requires it's spec
137+
func (r *AxoSyslogReconciler) reconcileWorkloadResources(log logr.Logger, axoSyslog *v1beta1.AxoSyslog) (*ctrl.Result, error) {
138+
resourceBuilders := []resources.ResourceWithSpec{
139+
axosyslogresources.StatefulSet,
140+
axosyslogresources.Service,
141+
axosyslogresources.HeadlessService,
142+
// TODO: service-metrics & buffer-metrics ?
143+
// axosyslogresources.ServiceMetrics,
144+
// axosyslogresources.ServiceBufferMetrics,
145+
}
146+
147+
for _, buildObject := range resourceBuilders {
148+
builderName := getFunctionName(buildObject)
149+
log.V(2).Info("Processing resource", "builder", builderName)
150+
151+
o, state, err := buildObject(axoSyslog)
152+
if err != nil {
153+
return nil, errors.WrapIff(err, "failed to build object with %s", builderName)
154+
}
155+
if o == nil {
156+
return nil, errors.Errorf("reconcile error: %s returned nil object", builderName)
157+
}
158+
159+
metaObj, ok := o.(metav1.Object)
160+
if !ok {
161+
return nil, errors.Errorf("reconcile error: %s returned non-metav1.Object", builderName)
162+
}
163+
164+
if metaObj.GetNamespace() == "" {
165+
return nil, errors.Errorf("reconcile error: %s returned resource without namespace set", builderName)
166+
}
167+
168+
if err := ctrl.SetControllerReference(axoSyslog, metaObj, r.Scheme()); err != nil {
169+
return nil, errors.WrapIff(err, "failed to set controller reference for %s", metaObj.GetName())
170+
}
171+
172+
result, err := r.ReconcileResource(o, state)
173+
if err != nil {
174+
return nil, errors.WrapIff(err, "failed to reconcile resource %s/%s", metaObj.GetNamespace(), metaObj.GetName())
175+
}
176+
if result != nil {
177+
return result, nil
178+
}
179+
}
180+
181+
return nil, nil
182+
}
183+
65184
func SetupAxoSyslogWithManager(mgr ctrl.Manager, logger logr.Logger) error {
66185
return ctrl.NewControllerManagedBy(mgr).
67186
For(&v1beta1.AxoSyslog{}).
68-
Named("AxoSyslogController").
69-
Complete(NewAxoSyslogReconciler(mgr.GetClient(), logger))
187+
Named("axosyslog").
188+
Complete(NewAxoSyslogReconciler(mgr.GetClient(), logger, reconciler.ReconcilerOpts{}))
189+
}
190+
191+
func getFunctionName(i any) string {
192+
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
70193
}

docs/configuration/crds/v1beta1/axosyslog_types.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,21 @@ AxoSyslog is the Schema for the AxoSyslogs API
1919

2020
AxoSyslogSpec defines the desired state of AxoSyslog
2121

22+
### configReloadImage (*BasicImageSpec, optional) {#axosyslogspec-configreloadimage}
23+
24+
ConfigReloadImage is the image specification for the config reload
25+
26+
2227
### destinations ([]Destination, optional) {#axosyslogspec-destinations}
2328

2429
Destinations is a list of destinations to be rendered in the AxoSyslog configuration
2530

2631

32+
### image (*BasicImageSpec, optional) {#axosyslogspec-image}
33+
34+
Image is the image specification for AxoSyslog
35+
36+
2737
### logPaths ([]LogPath, optional) {#axosyslogspec-logpaths}
2838

2939
LogPaths is a list of log paths to be rendered in the AxoSyslog configuration

pkg/resources/axosyslog/rbac.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright © 2022 Cisco Systems, Inc. and/or its affiliates
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package axosyslog
16+
17+
import (
18+
"github.com/cisco-open/operator-tools/pkg/reconciler"
19+
corev1 "k8s.io/api/core/v1"
20+
rbacv1 "k8s.io/api/rbac/v1"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
"k8s.io/apimachinery/pkg/runtime"
23+
)
24+
25+
const (
26+
LabelAppName = "app.kubernetes.io/name"
27+
LabelAppComponent = "app.kubernetes.io/component"
28+
commonAxoSyslogObjectValue = "axosyslog"
29+
)
30+
31+
func Role(namespace string) (runtime.Object, reconciler.DesiredState, error) {
32+
return &rbacv1.Role{
33+
ObjectMeta: metav1.ObjectMeta{
34+
Name: commonAxoSyslogObjectValue,
35+
Namespace: namespace,
36+
Labels: map[string]string{
37+
LabelAppName: commonAxoSyslogObjectValue,
38+
LabelAppComponent: commonAxoSyslogObjectValue,
39+
},
40+
},
41+
Rules: []rbacv1.PolicyRule{
42+
{
43+
APIGroups: []string{""},
44+
Resources: []string{"configmaps", "secrets"},
45+
Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"},
46+
},
47+
},
48+
}, reconciler.StatePresent, nil
49+
}
50+
51+
func RoleBinding(namespace string) (runtime.Object, reconciler.DesiredState, error) {
52+
return &rbacv1.RoleBinding{
53+
ObjectMeta: metav1.ObjectMeta{
54+
Name: commonAxoSyslogObjectValue,
55+
Namespace: namespace,
56+
Labels: map[string]string{
57+
LabelAppName: commonAxoSyslogObjectValue,
58+
LabelAppComponent: commonAxoSyslogObjectValue,
59+
},
60+
},
61+
RoleRef: rbacv1.RoleRef{
62+
Kind: "Role",
63+
APIGroup: rbacv1.GroupName,
64+
Name: commonAxoSyslogObjectValue,
65+
},
66+
Subjects: []rbacv1.Subject{
67+
{
68+
Kind: rbacv1.ServiceAccountKind,
69+
Name: commonAxoSyslogObjectValue,
70+
Namespace: namespace,
71+
},
72+
},
73+
}, reconciler.StatePresent, nil
74+
}
75+
76+
func ServiceAccount(namespace string) (runtime.Object, reconciler.DesiredState, error) {
77+
// TODO: Implement STS overrides
78+
// err := merge.Merge(account, r.axoSyslogSpec.ServiceAccountOverrides)
79+
80+
return &corev1.ServiceAccount{
81+
ObjectMeta: metav1.ObjectMeta{
82+
Name: commonAxoSyslogObjectValue,
83+
Namespace: namespace,
84+
Labels: map[string]string{
85+
LabelAppName: commonAxoSyslogObjectValue,
86+
LabelAppComponent: commonAxoSyslogObjectValue,
87+
},
88+
},
89+
}, reconciler.StatePresent, nil
90+
}

0 commit comments

Comments
 (0)