@@ -18,7 +18,6 @@ package controller
1818
1919import (
2020 "context"
21- "fmt"
2221 "log/slog"
2322
2423 "cuelang.org/go/cue/cuecontext"
@@ -27,31 +26,26 @@ import (
2726 "sigs.k8s.io/controller-runtime/pkg/client"
2827 "sigs.k8s.io/controller-runtime/pkg/log"
2928
30- api "github.com/input-output-hk/catalyst-forge/foundry/api/client"
31-
3229 foundryv1alpha1 "github.com/input-output-hk/catalyst-forge/foundry/operator/api/v1alpha1"
3330 "github.com/input-output-hk/catalyst-forge/foundry/operator/pkg/config"
31+ "github.com/input-output-hk/catalyst-forge/foundry/operator/pkg/handlers"
3432 "github.com/input-output-hk/catalyst-forge/lib/project/deployment"
3533 depl "github.com/input-output-hk/catalyst-forge/lib/project/deployment/deployer"
36- "github.com/input-output-hk/catalyst-forge/lib/project/providers"
3734 "github.com/input-output-hk/catalyst-forge/lib/project/secrets"
38- "github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy"
39- "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo"
4035 "github.com/input-output-hk/catalyst-forge/lib/tools/git/repo/remote"
4136)
4237
4338// ReleaseDeploymentReconciler reconciles a Release object
4439type ReleaseDeploymentReconciler struct {
4540 client.Client
46- ApiClient api.Client
47- Config config.OperatorConfig
48- FsDeploy * billy.BillyFs
49- FsSource * billy.BillyFs
50- Logger * slog.Logger
51- ManifestStore deployment.ManifestGeneratorStore
52- Remote remote.GitRemoteInteractor
53- Scheme * runtime.Scheme
54- SecretStore secrets.SecretStore
41+ Config config.OperatorConfig
42+ DeploymentHandler * handlers.ReleaseDeploymentHandler
43+ Logger * slog.Logger
44+ ManifestStore deployment.ManifestGeneratorStore
45+ Remote remote.GitRemoteInteractor
46+ RepoHandler * handlers.RepoHandler
47+ Scheme * runtime.Scheme
48+ SecretStore secrets.SecretStore
5549}
5650
5751// +kubebuilder:rbac:groups=foundry.projectcatalyst.io,resources=releases,verbs=get;list;watch;create;update;patch;delete
@@ -70,35 +64,34 @@ func (r *ReleaseDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Re
7064
7165 // 2. Fetch the associated ReleaseDeployment from the API
7266 log .Info ("Fetching release deployment from API" , "releaseID" , resource .Spec .ReleaseID , "deploymentID" , resource .Spec .ID )
73- releaseDeployment , err := r .ApiClient .GetDeployment (ctx , resource .Spec .ReleaseID , resource .Spec .ID )
74- if err != nil {
75- log .Error (err , "unable to fetch deployment" )
67+ if err := r .DeploymentHandler .Load (& resource ); err != nil {
68+ log .Error (err , "unable to load deployment" )
7669 return ctrl.Result {}, err
77- } else if releaseDeployment == nil {
78- log .Error (err , "unable to find deployment" )
79- return ctrl.Result {}, fmt .Errorf ("unable to find deployment" )
8070 }
81- release := releaseDeployment . Release
71+ release := r . DeploymentHandler . Release ()
8272
8373 // 3. Check if the deployment has already been completed
84- if isDeploymentComplete ( releaseDeployment . Status ) {
85- log .Info ("Deployment already succeeded " )
74+ if r . DeploymentHandler . IsCompleted ( ) {
75+ log .Info ("Deployment already finished " )
8676 return ctrl.Result {}, nil
8777 }
8878
89- // 4. Set deployment status to running if not already set
90- log .Info ("Checking deployment status" , "status" , releaseDeployment .Status )
91- if releaseDeployment .Status != api .DeploymentStatusRunning {
92- if err := r .ApiClient .UpdateDeploymentStatus (
93- ctx ,
94- release .ID ,
95- releaseDeployment .ID ,
96- api .DeploymentStatusRunning ,
97- "Deployment in progress" ,
98- ); err != nil {
99- log .Error (err , "unable to update deployment" )
79+ // 4. Check if max attempts have been reached
80+ if r .DeploymentHandler .MaxAttemptsReached (r .Config .MaxAttempts - 1 ) {
81+ log .Info ("Max attempts reached, setting deployment to failed" )
82+ if err := r .DeploymentHandler .SetFailed ("Max attempts reached" ); err != nil {
83+ log .Error (err , "unable to set deployment status to failed" )
84+ r .DeploymentHandler .AddErrorEvent (nil , "Max attempts reached" )
10085 return ctrl.Result {}, err
10186 }
87+
88+ return ctrl.Result {}, nil
89+ }
90+
91+ // 5. Set deployment status to running if not already set
92+ if err := r .DeploymentHandler .SetRunning (); err != nil {
93+ log .Error (err , "unable to set deployment status to running" )
94+ return ctrl.Result {}, err
10295 }
10396
10497 // resource.Status.State = "Deploying"
@@ -107,35 +100,26 @@ func (r *ReleaseDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Re
107100 // return ctrl.Result{}, err
108101 // }
109102
110- // 5. Get the git auth token for repos
111- log .Info ("Fetching git auth token" )
112- token , err := r .getAuth ()
113- if err != nil {
114- log .Error (err , "unable to get auth token" )
115- return ctrl.Result {}, err
116- }
117- fmt .Println ("token" , token )
118-
119103 // 6. Open repos
120104 log .Info ("Opening deployment repo" , "url" , r .Config .Deployer .Git .Url )
121- deployRepo , err := r .getDeployRepo (token )
122- if err != nil {
123- log .Error (err , "unable to get deployment repo" )
105+ if err := r .RepoHandler .LoadDeploymentRepo (r .Config .Deployer .Git .Url , r .Config .Deployer .Git .Ref ); err != nil {
106+ log .Error (err , "unable to load deployment repo" )
124107 return ctrl.Result {}, err
125108 }
126109
127110 log .Info ("Opening source repo" , "url" , release .SourceRepo )
128- sourceRepo , err := r .getSourceRepo ( token , release )
129- if err != nil {
130- log . Error (err , "unable to create repo" )
111+ if err := r .RepoHandler . LoadSourceRepo ( release . SourceRepo , release . SourceCommit ); err != nil {
112+ log . Error ( err , "unable to load source repo" )
113+ r . DeploymentHandler . AddErrorEvent (err , "Unable to load source repo" )
131114 return ctrl.Result {}, err
132115 }
133116
134117 // 7. Fetch the bundle from the source repo
135118 log .Info ("Fetching bundle from source repo" , "url" , release .SourceRepo , "commit" , release .SourceCommit )
136- bundle , err := deployment .FetchBundle (sourceRepo , release .ProjectPath , r .SecretStore , r .Logger )
119+ bundle , err := deployment .FetchBundle (* r . RepoHandler . SourceRepo () , release .ProjectPath , r .SecretStore , r .Logger )
137120 if err != nil {
138121 log .Error (err , "unable to fetch bundle" )
122+ r .DeploymentHandler .AddErrorEvent (err , "Unable to fetch deployment bundle" )
139123 return ctrl.Result {}, err
140124 }
141125
@@ -153,111 +137,32 @@ func (r *ReleaseDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Re
153137 resource .Spec .ID ,
154138 release .Project ,
155139 bundle ,
156- depl .WithRepo (& deployRepo ),
140+ depl .WithRepo (r . RepoHandler . DeploymentRepo () ),
157141 )
158142 if err != nil {
159143 log .Error (err , "unable to create deployment" )
144+ r .DeploymentHandler .AddErrorEvent (err , "Unable to create deployment" )
160145 return ctrl.Result {}, err
161146 }
162147
163148 // 9. Commit and push the deployment
164149 log .Info ("Committing and pushing deployment" )
165150 if err := deployment .Commit (); err != nil {
166151 log .Error (err , "unable to commit deployment" )
152+ r .DeploymentHandler .AddErrorEvent (err , "Unable to commit deployment" )
167153 return ctrl.Result {}, err
168154 }
169155
170156 // 10. Update the deployment status to succeeded
171- log .Info ("Updating deployment status to succeeded" )
172- if err := r .ApiClient .UpdateDeploymentStatus (
173- ctx ,
174- release .ID ,
175- releaseDeployment .ID ,
176- api .DeploymentStatusSucceeded ,
177- "Deployment succeeded" ,
178- ); err != nil {
179- log .Error (err , "unable to update deployment" )
157+ log .Info ("Deployment succeeded" )
158+ if err := r .DeploymentHandler .SetSucceeded (); err != nil {
159+ log .Error (err , "unable to set deployment status to succeeded" )
180160 return ctrl.Result {}, err
181161 }
182162
183163 return ctrl.Result {}, nil
184164}
185165
186- func (r * ReleaseDeploymentReconciler ) getAuth () (string , error ) {
187- creds , err := providers .GetGitProviderCreds (& r .Config .Deployer .Git .Creds , & r .SecretStore , r .Logger )
188- if err != nil {
189- return "" , err
190- }
191-
192- return creds .Token , nil
193- }
194-
195- func (r * ReleaseDeploymentReconciler ) getDeployRepo (token string ) (repo.GitRepo , error ) {
196- var dfs * billy.BillyFs
197- if r .FsDeploy == nil {
198- dfs = billy .NewInMemoryFs ()
199- } else {
200- dfs = r .FsDeploy
201- }
202-
203- rp , err := repo .NewCachedRepo (
204- r .Config .Deployer .Git .Url ,
205- r .Logger ,
206- repo .WithFS (dfs ),
207- repo .WithGitRemoteInteractor (r .Remote ),
208- repo .WithAuth ("forge" , token ),
209- )
210- if err != nil {
211- return repo.GitRepo {}, err
212- }
213-
214- if err := rp .CheckoutBranch (r .Config .Deployer .Git .Ref ); err != nil {
215- return repo.GitRepo {}, fmt .Errorf ("failed to checkout branch %s: %w" , r .Config .Deployer .Git .Ref , err )
216- }
217-
218- if err := rp .Pull (); err != nil && ! repo .IsErrNoUpdates (err ) {
219- return repo.GitRepo {}, fmt .Errorf ("failed to pull latest changes from branch %s: %w" , r .Config .Deployer .Git .Ref , err )
220- }
221-
222- return rp , nil
223- }
224-
225- func (r * ReleaseDeploymentReconciler ) getSourceRepo (token string , release * api.Release ) (repo.GitRepo , error ) {
226- var sfs * billy.BillyFs
227- if r .FsSource == nil {
228- sfs = billy .NewBaseOsFS ()
229- } else {
230- sfs = r .FsSource
231- }
232-
233- rp , err := repo .NewCachedRepo (
234- release .SourceRepo ,
235- r .Logger ,
236- repo .WithFS (sfs ),
237- repo .WithGitRemoteInteractor (r .Remote ),
238- repo .WithAuth ("forge" , token ),
239- )
240- if err != nil {
241- return repo.GitRepo {}, err
242- }
243-
244- if err := rp .Fetch (); err != nil && ! repo .IsErrNoUpdates (err ) {
245- return repo.GitRepo {}, fmt .Errorf ("failed to fetch latest changes: %w" , err )
246- }
247-
248- if err := rp .CheckoutCommit (release .SourceCommit ); err != nil {
249- return repo.GitRepo {}, fmt .Errorf ("failed to checkout commit %s: %w" , release .SourceCommit , err )
250- }
251-
252- return rp , nil
253- }
254-
255- // isDeploymentComplete checks if the deployment is complete
256- // by checking if the status is either Succeeded or Failed.
257- func isDeploymentComplete (status api.DeploymentStatus ) bool {
258- return status == api .DeploymentStatusSucceeded || status == api .DeploymentStatusFailed
259- }
260-
261166// SetupWithManager sets up the controller with the Manager.
262167func (r * ReleaseDeploymentReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
263168 return ctrl .NewControllerManagedBy (mgr ).
0 commit comments