UNCLASSIFIED

Commit 4fab46f1 authored by Jason van Brackel's avatar Jason van Brackel
Browse files

feat: Add delete funcationality to projects

parent e6380b06
...@@ -128,8 +128,6 @@ func (r *GroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl ...@@ -128,8 +128,6 @@ func (r *GroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
} }
// Delete the Group if required // Delete the Group if required
// name of our custom finalizer
// examine DeletionTimestamp to determine if object is under deletion // examine DeletionTimestamp to determine if object is under deletion
if group.ObjectMeta.DeletionTimestamp.IsZero() { if group.ObjectMeta.DeletionTimestamp.IsZero() {
// The object is not being deleted, so if it does not have our finalizer, // The object is not being deleted, so if it does not have our finalizer,
...@@ -470,7 +468,7 @@ func (r *GroupReconciler) deleteProjectsAndGitlabGroup(ctx context.Context, grou ...@@ -470,7 +468,7 @@ func (r *GroupReconciler) deleteProjectsAndGitlabGroup(ctx context.Context, grou
r.Log.Error(err, errorWhileDeletingGroup) r.Log.Error(err, errorWhileDeletingGroup)
return err return err
} }
if err = r.updateState(ctx, group, errorWhileDeletingGroup); err != nil { if err = r.updateState(ctx, group, "Terminating"); err != nil {
return err return err
} }
......
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"strconv" "strconv"
apisGitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab" apisGitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab"
"valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1"
...@@ -55,6 +56,8 @@ const ( ...@@ -55,6 +56,8 @@ const (
errorGettingProjectVariableFromGitlab = "Error getting project variable from Gitlab" errorGettingProjectVariableFromGitlab = "Error getting project variable from Gitlab"
errorCreatingProjectVariableInGitlab = "Error creating project variable in Gitlab" errorCreatingProjectVariableInGitlab = "Error creating project variable in Gitlab"
errorWhileUpdatingProjectVariableInGitlab = "Error while updating project variable in gitlab" errorWhileUpdatingProjectVariableInGitlab = "Error while updating project variable in gitlab"
errorRunningProjectFinalizer = "Error running project deleting finalizer"
errorWhileDeletingProject = "Error while deleting project"
) )
// statuses // statuses
...@@ -67,6 +70,8 @@ const ManifestImageVariableName = "MANIFEST_IMAGE" ...@@ -67,6 +70,8 @@ const ManifestImageVariableName = "MANIFEST_IMAGE"
const annotationKeyID = "ID" const annotationKeyID = "ID"
const projectFinalizerName = "valkyrie.dso.mil/valkyrie-api/apis/gitlab/project/finalizer"
// Reconcile is the main reconciliation loop that will create/edit/delete Gitlab Projects. // Reconcile is the main reconciliation loop that will create/edit/delete Gitlab Projects.
func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.Log = r.Log.WithValues("project", req.NamespacedName) r.Log = r.Log.WithValues("project", req.NamespacedName)
...@@ -97,8 +102,42 @@ func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct ...@@ -97,8 +102,42 @@ func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
} }
} }
// Delete the Group if required
// examine DeletionTimestamp to determine if object is under deletion
if project.ObjectMeta.DeletionTimestamp.IsZero() {
// The object is not being deleted, so if it does not have our finalizer,
// then lets add the finalizer and update the object. This is equivalent
// registering our finalizer.
if !containsString(project.GetFinalizers(), projectFinalizerName) {
controllerutil.AddFinalizer(project, projectFinalizerName)
if err = r.Update(ctx, project); err != nil {
r.Log.Error(err, errorAddingFinalizer)
return ctrl.Result{}, err
}
}
} else {
// The object is being deleted
if containsString(project.GetFinalizers(), projectFinalizerName) {
// our finalizer is present, so lets handle any external dependency
if err = r.deleteProjectsFromGitlab(project); err != nil {
r.Log.Error(err, errorRunningProjectFinalizer)
return ctrl.Result{}, err
}
// remove our finalizer from the list and update it.
controllerutil.RemoveFinalizer(project, groupFinalizerName)
if err = r.Update(ctx, project); err != nil {
r.Log.Error(err, errorRemovingFinalizer)
return ctrl.Result{}, err
}
}
// Stop reconciliation as the item is being deleted
return ctrl.Result{}, nil
}
// Make Sure the Group Exists in Gitlab // Make Sure the Group Exists in Gitlab
if _, err = r.getGitlabGroup(ctx, project, req); err != nil { if _, err = r.getGitlabGroup(project); err != nil {
r.Log.Error(err, errorGettingGroupFromGitlab, "request", req) r.Log.Error(err, errorGettingGroupFromGitlab, "request", req)
_ = r.updateStatus(ctx, project, groupDoesntExist) _ = r.updateStatus(ctx, project, groupDoesntExist)
return ctrl.Result{Requeue: true}, err return ctrl.Result{Requeue: true}, err
...@@ -169,7 +208,7 @@ func (r *ProjectReconciler) getProject(ctx context.Context, request ctrl.Request ...@@ -169,7 +208,7 @@ func (r *ProjectReconciler) getProject(ctx context.Context, request ctrl.Request
return &project, nil return &project, nil
} }
func (r *ProjectReconciler) getGitlabGroup(ctx context.Context, project *v1alpha1.Project, req ctrl.Request) (*gitlab.Group, error) { func (r *ProjectReconciler) getGitlabGroup(project *v1alpha1.Project) (*gitlab.Group, error) {
var gitlabGroup *gitlab.Group var gitlabGroup *gitlab.Group
var response int var response int
var err error var err error
...@@ -286,3 +325,22 @@ func (r *ProjectReconciler) updateManifestImageSetting(id int, manifestPath stri ...@@ -286,3 +325,22 @@ func (r *ProjectReconciler) updateManifestImageSetting(id int, manifestPath stri
return projectVariable, err return projectVariable, err
} }
func (r *ProjectReconciler) deleteProjectsFromGitlab(project *v1alpha1.Project) error {
var id int
var err error
var statusCode int
id, _ = strconv.Atoi(project.ObjectMeta.Annotations["ID"])
if statusCode, err = r.gitlabClient.DeleteProject(id, 0, 0); err != nil {
if statusCode == 404 {
// Assume it's deleted
return nil
}
r.Log.Error(err, errorWhileDeletingProject, "statusCode", statusCode)
return err
}
return nil
}
...@@ -397,26 +397,19 @@ var _ = Describe("reconcile", func() { ...@@ -397,26 +397,19 @@ var _ = Describe("reconcile", func() {
}) })
}) })
Context("updateProjectIDAnnotation returns an error", func() { Context("updateProjectIDAnnotation returns an error", func() {
sut, _, log, _ := getProjectControllerWithMocksInGreenTestState() sut, _, _, _ := getProjectControllerWithMocksInGreenTestState()
sut.Client.(*MockClient).UpdateFunction = func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { sut.Client.(*MockClient).UpdateFunction = func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
return &MockError{message: errorUpdatingProjectIDAnnotation} return &MockError{message: errorUpdatingProjectIDAnnotation}
} }
request := getGreenProjectRequest() project := getGreenProject()
err := sut.updateProjectIDAnnotation(context.TODO(), &project, &gitlab.Project{ ID: 1})
result, err := sut.Reconcile(context.TODO(), request)
It("should return an error", func() { It("should return an error", func() {
Expect(err).ToNot(BeNil()) Expect(err).ToNot(BeNil())
}) })
It("should requeue the object", func() {
Expect(result).To(Equal(ctrl.Result{Requeue: true}))
})
It("should log the error", func() {
Expect(log.logLevelCalled).To(Equal("Error"))
Expect(log.loggedMessage).To(Equal(errorUpdatingProjectIDAnnotation))
})
}) })
}) })
...@@ -480,7 +473,7 @@ var _ = Describe("getGitlabGroup", func() { ...@@ -480,7 +473,7 @@ var _ = Describe("getGitlabGroup", func() {
Context("green state", func() { Context("green state", func() {
sut, _, _, _ := getProjectControllerWithMocksInGreenTestState() sut, _, _, _ := getProjectControllerWithMocksInGreenTestState()
project := getGreenProject() project := getGreenProject()
group, err := sut.getGitlabGroup(context.TODO(), &project, getGreenProjectRequest()) group, err := sut.getGitlabGroup(&project)
It("should return a group, and no error.", func() { It("should return a group, and no error.", func() {
Expect(group).To(BeAssignableToTypeOf(&gitlab.Group{})) Expect(group).To(BeAssignableToTypeOf(&gitlab.Group{}))
Expect(err).To(BeNil()) Expect(err).To(BeNil())
...@@ -494,7 +487,7 @@ var _ = Describe("getGitlabGroup", func() { ...@@ -494,7 +487,7 @@ var _ = Describe("getGitlabGroup", func() {
message: "failure in getGitlabGroup", message: "failure in getGitlabGroup",
} }
} }
group, err := sut.getGitlabGroup(context.TODO(), &project, getGreenProjectRequest()) group, err := sut.getGitlabGroup(&project)
It("should return an error", func() { It("should return an error", func() {
Expect(err).ToNot(BeNil()) Expect(err).ToNot(BeNil())
}) })
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment