@@ -18,6 +18,10 @@ package controllers
1818
1919import (
2020 "context"
21+ "fmt"
22+ "io/ioutil"
23+ "net/http"
24+ "os"
2125 "strings"
2226 "time"
2327
@@ -27,6 +31,7 @@ import (
2731 "sigs.k8s.io/controller-runtime/pkg/client"
2832
2933 sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
34+ "github.com/stefanprodan/source-watcher/pkg/untar"
3035)
3136
3237// GitRepositoryWatcher watches GitRepository objects for revision changes
@@ -40,9 +45,11 @@ type GitRepositoryWatcher struct {
4045// +kubebuilder:rbac:groups=source.fluxcd.io,resources=gitrepositories/status,verbs=get
4146
4247func (r * GitRepositoryWatcher ) Reconcile (req ctrl.Request ) (ctrl.Result , error ) {
48+ // set timeout for the reconciliation
4349 ctx , cancel := context .WithTimeout (context .Background (), 15 * time .Second )
4450 defer cancel ()
4551
52+ // get source object
4653 var repository sourcev1.GitRepository
4754 if err := r .Get (ctx , req .NamespacedName , & repository ); err != nil {
4855 return ctrl.Result {}, client .IgnoreNotFound (err )
@@ -51,6 +58,32 @@ func (r *GitRepositoryWatcher) Reconcile(req ctrl.Request) (ctrl.Result, error)
5158 log := r .Log .WithValues (strings .ToLower (repository .Kind ), req .NamespacedName )
5259 log .Info ("New revision detected" , "revision" , repository .Status .Artifact .Revision )
5360
61+ // create tmp dir
62+ tmpDir , err := ioutil .TempDir ("" , repository .Name )
63+ if err != nil {
64+ return ctrl.Result {}, fmt .Errorf ("failed to create temp dir, error: %w" , err )
65+ }
66+ defer os .RemoveAll (tmpDir )
67+
68+ // download and extract artifact
69+ summary , err := r .fetchArtifact (ctx , repository , tmpDir )
70+ if err != nil {
71+ log .Error (err , "unable to fetch artifact" )
72+ return ctrl.Result {}, err
73+ }
74+ log .Info (summary )
75+
76+ // list artifact content
77+ files , err := ioutil .ReadDir (tmpDir )
78+ if err != nil {
79+ return ctrl.Result {}, fmt .Errorf ("faild to list files, error: %w" , err )
80+ }
81+
82+ // do something with the artifact content
83+ for _ , f := range files {
84+ log .Info ("Processing " + f .Name ())
85+ }
86+
5487 return ctrl.Result {}, nil
5588}
5689
@@ -60,3 +93,43 @@ func (r *GitRepositoryWatcher) SetupWithManager(mgr ctrl.Manager) error {
6093 WithEventFilter (GitRepositoryRevisionChangePredicate {}).
6194 Complete (r )
6295}
96+
97+ func (r * GitRepositoryWatcher ) fetchArtifact (ctx context.Context , repository sourcev1.GitRepository , dir string ) (string , error ) {
98+ if repository .Status .Artifact == nil {
99+ return "" , fmt .Errorf ("respository %s does not containt an artifact" , repository .Name )
100+ }
101+
102+ url := repository .Status .Artifact .URL
103+
104+ // for local run:
105+ // kubectl -n gitops-system port-forward svc/source-controller 8080:80
106+ // export SOURCE_HOST=localhost:8080
107+ if hostname := os .Getenv ("SOURCE_HOST" ); hostname != "" {
108+ url = fmt .Sprintf ("http://%s/gitrepository/%s/%s/latest.tar.gz" , hostname , repository .Namespace , repository .Name )
109+ }
110+
111+ // download the tarball
112+ req , err := http .NewRequest ("GET" , url , nil )
113+ if err != nil {
114+ return "" , fmt .Errorf ("failed to create HTTP request, error: %w" , err )
115+ }
116+
117+ resp , err := http .DefaultClient .Do (req .WithContext (ctx ))
118+ if err != nil {
119+ return "" , fmt .Errorf ("failed to download artifact from %s, error: %w" , url , err )
120+ }
121+ defer resp .Body .Close ()
122+
123+ // check response
124+ if resp .StatusCode != http .StatusOK {
125+ return "" , fmt .Errorf ("faild to download artifact, status: %s" , resp .Status )
126+ }
127+
128+ // extract
129+ summary , err := untar .Untar (resp .Body , dir )
130+ if err != nil {
131+ return "" , fmt .Errorf ("faild to untar artifact, error: %w" , err )
132+ }
133+
134+ return summary , nil
135+ }
0 commit comments