Skip to content

Commit 4311e98

Browse files
committed
Add Git source watcher controller
1 parent 2a32d2d commit 4311e98

File tree

4 files changed

+240
-0
lines changed

4 files changed

+240
-0
lines changed

config/rbac/role.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
---
3+
apiVersion: rbac.authorization.k8s.io/v1
4+
kind: ClusterRole
5+
metadata:
6+
creationTimestamp: null
7+
name: manager-role
8+
rules:
9+
- apiGroups:
10+
- source.fluxcd.io
11+
resources:
12+
- gitrepositories
13+
verbs:
14+
- get
15+
- list
16+
- watch
17+
- apiGroups:
18+
- source.fluxcd.io
19+
resources:
20+
- gitrepositories/status
21+
verbs:
22+
- get
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
Copyright 2020 The Flux CD contributors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controllers
18+
19+
import (
20+
"sigs.k8s.io/controller-runtime/pkg/event"
21+
"sigs.k8s.io/controller-runtime/pkg/predicate"
22+
23+
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
24+
)
25+
26+
// GitRepositoryRevisionChangePredicate triggers an update event
27+
// when a Git source revision changes
28+
type GitRepositoryRevisionChangePredicate struct {
29+
predicate.Funcs
30+
}
31+
32+
func (GitRepositoryRevisionChangePredicate) Update(e event.UpdateEvent) bool {
33+
if e.MetaOld == nil || e.MetaNew == nil {
34+
return false
35+
}
36+
37+
oldRepo, ok := e.ObjectOld.(*sourcev1.GitRepository)
38+
if !ok {
39+
return false
40+
}
41+
42+
newRepo, ok := e.ObjectNew.(*sourcev1.GitRepository)
43+
if !ok {
44+
return false
45+
}
46+
47+
if oldRepo.GetArtifact() == nil && newRepo.GetArtifact() != nil {
48+
return true
49+
}
50+
51+
if oldRepo.GetArtifact() != nil && newRepo.GetArtifact() != nil &&
52+
oldRepo.GetArtifact().Revision != newRepo.GetArtifact().Revision {
53+
return true
54+
}
55+
56+
return false
57+
}
58+
59+
func (GitRepositoryRevisionChangePredicate) Create(e event.CreateEvent) bool {
60+
return false
61+
}
62+
63+
func (GitRepositoryRevisionChangePredicate) Delete(e event.DeleteEvent) bool {
64+
return false
65+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
Copyright 2020 The Flux CD contributors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controllers
18+
19+
import (
20+
"context"
21+
"strings"
22+
"time"
23+
24+
"github.com/go-logr/logr"
25+
"k8s.io/apimachinery/pkg/runtime"
26+
ctrl "sigs.k8s.io/controller-runtime"
27+
"sigs.k8s.io/controller-runtime/pkg/client"
28+
29+
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
30+
)
31+
32+
// GitRepositoryWatcher watches GitRepository objects for revision changes
33+
type GitRepositoryWatcher struct {
34+
client.Client
35+
Log logr.Logger
36+
Scheme *runtime.Scheme
37+
}
38+
39+
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=gitrepositories,verbs=get;list;watch
40+
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=gitrepositories/status,verbs=get
41+
42+
func (r *GitRepositoryWatcher) Reconcile(req ctrl.Request) (ctrl.Result, error) {
43+
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
44+
defer cancel()
45+
46+
var repository sourcev1.GitRepository
47+
if err := r.Get(ctx, req.NamespacedName, &repository); err != nil {
48+
return ctrl.Result{}, client.IgnoreNotFound(err)
49+
}
50+
51+
log := r.Log.WithValues(strings.ToLower(repository.Kind), req.NamespacedName)
52+
log.Info("New revision detected", "revision", repository.Status.Artifact.Revision)
53+
54+
return ctrl.Result{}, nil
55+
}
56+
57+
func (r *GitRepositoryWatcher) SetupWithManager(mgr ctrl.Manager) error {
58+
return ctrl.NewControllerManagedBy(mgr).
59+
For(&sourcev1.GitRepository{}).
60+
WithEventFilter(GitRepositoryRevisionChangePredicate{}).
61+
Complete(r)
62+
}

main.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"flag"
21+
"os"
22+
23+
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
24+
25+
"k8s.io/apimachinery/pkg/runtime"
26+
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
27+
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
28+
ctrl "sigs.k8s.io/controller-runtime"
29+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
30+
31+
"github.com/stefanprodan/source-watcher/controllers"
32+
// +kubebuilder:scaffold:imports
33+
)
34+
35+
var (
36+
scheme = runtime.NewScheme()
37+
setupLog = ctrl.Log.WithName("setup")
38+
)
39+
40+
func init() {
41+
_ = clientgoscheme.AddToScheme(scheme)
42+
_ = sourcev1.AddToScheme(scheme)
43+
44+
// +kubebuilder:scaffold:scheme
45+
}
46+
47+
func main() {
48+
var (
49+
metricsAddr string
50+
enableLeaderElection bool
51+
logJSON bool
52+
)
53+
54+
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
55+
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
56+
"Enable leader election for controller manager. "+
57+
"Enabling this will ensure there is only one active controller manager.")
58+
flag.BoolVar(&logJSON, "log-json", false, "Set logging to JSON format.")
59+
flag.Parse()
60+
61+
ctrl.SetLogger(zap.New(zap.UseDevMode(!logJSON)))
62+
63+
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
64+
Scheme: scheme,
65+
MetricsBindAddress: metricsAddr,
66+
Port: 9443,
67+
LeaderElection: enableLeaderElection,
68+
LeaderElectionID: "0cf1c86c.fluxcd.io",
69+
})
70+
if err != nil {
71+
setupLog.Error(err, "unable to start manager")
72+
os.Exit(1)
73+
}
74+
75+
if err = (&controllers.GitRepositoryWatcher{
76+
Client: mgr.GetClient(),
77+
Log: ctrl.Log.WithName("controllers").WithName("GitRepositoryWatcher"),
78+
Scheme: mgr.GetScheme(),
79+
}).SetupWithManager(mgr); err != nil {
80+
setupLog.Error(err, "unable to create controller", "controller", "GitRepositoryWatcher")
81+
os.Exit(1)
82+
}
83+
84+
// +kubebuilder:scaffold:builder
85+
86+
setupLog.Info("starting manager")
87+
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
88+
setupLog.Error(err, "problem running manager")
89+
os.Exit(1)
90+
}
91+
}

0 commit comments

Comments
 (0)