-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor deployment status tests (#1027)
- Loading branch information
Showing
3 changed files
with
320 additions
and
369 deletions.
There are no files selected for viewing
320 changes: 320 additions & 0 deletions
320
internal/controller/applicationdeploymentstatus_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,320 @@ | ||
package controller | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"time" | ||
|
||
argocdv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" | ||
"github.com/argoproj/gitops-engine/pkg/health" | ||
synccommon "github.com/argoproj/gitops-engine/pkg/sync/common" | ||
"github.com/int128/argocd-commenter/internal/controller/githubmock" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
crclient "sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
var _ = Describe("Deployment status", func() { | ||
var app argocdv1alpha1.Application | ||
var deploymentStatus githubmock.DeploymentStatus | ||
|
||
BeforeEach(func(ctx context.Context) { | ||
By("Setting up a deployment status endpoint") | ||
deploymentStatus = githubmock.DeploymentStatus{} | ||
githubServer.AddHandlers(map[string]http.Handler{ | ||
"GET /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.ListEndpoint(), | ||
"POST /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.CreateEndpoint(), | ||
}) | ||
|
||
By("Creating an application") | ||
app = argocdv1alpha1.Application{ | ||
TypeMeta: metav1.TypeMeta{ | ||
APIVersion: "argoproj.io/v1alpha1", | ||
Kind: "Application", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
GenerateName: "fixture-deployment-status-phase-", | ||
Namespace: "default", | ||
Annotations: map[string]string{ | ||
"argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/owner/repo-deployment/deployments/101", | ||
}, | ||
}, | ||
Spec: argocdv1alpha1.ApplicationSpec{ | ||
Project: "default", | ||
Source: &argocdv1alpha1.ApplicationSource{ | ||
RepoURL: "https://github.com/owner/repo-deployment.git", | ||
Path: "test", | ||
TargetRevision: "main", | ||
}, | ||
Destination: argocdv1alpha1.ApplicationDestination{ | ||
Server: "https://kubernetes.default.svc", | ||
Namespace: "default", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed()) | ||
}) | ||
|
||
Context("When the application is synced", func() { | ||
BeforeEach(func(ctx context.Context) { | ||
By("Updating the application to running") | ||
startedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationRunning, | ||
StartedAt: startedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) | ||
|
||
By("Updating the application to succeeded") | ||
finishedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationSucceeded, | ||
StartedAt: startedAt, | ||
FinishedAt: &finishedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) | ||
}) | ||
|
||
Context("When the application is healthy", func() { | ||
It("Should create deployment statuses", func(ctx context.Context) { | ||
By("Updating the application to progressing") | ||
app.Status.Health = argocdv1alpha1.HealthStatus{ | ||
Status: health.HealthStatusProgressing, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
|
||
By("Updating the application to healthy") | ||
app.Status.Health = argocdv1alpha1.HealthStatus{ | ||
Status: health.HealthStatusHealthy, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(3)) | ||
}, SpecTimeout(3*time.Second)) | ||
|
||
It("Should not create any deployment status after healthy", func(ctx context.Context) { | ||
By("Updating the application to progressing") | ||
app.Status.Health = argocdv1alpha1.HealthStatus{ | ||
Status: health.HealthStatusProgressing, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
|
||
By("Updating the application to healthy") | ||
app.Status.Health = argocdv1alpha1.HealthStatus{ | ||
Status: health.HealthStatusHealthy, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(3)) | ||
|
||
By("Updating the application to progressing") | ||
app.Status.Health = argocdv1alpha1.HealthStatus{ | ||
Status: health.HealthStatusProgressing, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
|
||
By("Updating the application to healthy") | ||
app.Status.Health = argocdv1alpha1.HealthStatus{ | ||
Status: health.HealthStatusHealthy, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(Equal(3)) | ||
|
||
By("Updating the application to running") | ||
startedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationRunning, | ||
StartedAt: startedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
|
||
By("Updating the application to succeeded") | ||
finishedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationSucceeded, | ||
StartedAt: startedAt, | ||
FinishedAt: &finishedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(Equal(3)) | ||
}, SpecTimeout(3*time.Second)) | ||
}) | ||
}) | ||
|
||
Context("When the sync operation is failed", func() { | ||
It("Should create deployment statuses", func(ctx context.Context) { | ||
By("Updating the application to running") | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationRunning, | ||
StartedAt: metav1.Now(), | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) | ||
|
||
By("Updating the application to retrying") | ||
startedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationRunning, | ||
StartedAt: startedAt, | ||
RetryCount: 1, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Consistently(func() int { return deploymentStatus.CreateCount() }, 100*time.Millisecond).Should(Equal(1)) | ||
|
||
By("Updating the application to failed") | ||
finishedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationFailed, | ||
StartedAt: startedAt, | ||
FinishedAt: &finishedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) | ||
}, SpecTimeout(3*time.Second)) | ||
}) | ||
}) | ||
|
||
var _ = Describe("Deployment status", func() { | ||
Context("When an application was synced before the deployment annotation is updated", func() { | ||
var app argocdv1alpha1.Application | ||
|
||
BeforeEach(func(ctx context.Context) { | ||
By("Creating an application") | ||
app = argocdv1alpha1.Application{ | ||
TypeMeta: metav1.TypeMeta{ | ||
APIVersion: "argoproj.io/v1alpha1", | ||
Kind: "Application", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
GenerateName: "fixture-deployment-status-phase-", | ||
Namespace: "default", | ||
Annotations: map[string]string{ | ||
"argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/owner/repo-deployment/deployments/999", | ||
}, | ||
}, | ||
Spec: argocdv1alpha1.ApplicationSpec{ | ||
Project: "default", | ||
Source: &argocdv1alpha1.ApplicationSource{ | ||
RepoURL: "https://github.com/owner/repo-deployment.git", | ||
Path: "test", | ||
TargetRevision: "main", | ||
}, | ||
Destination: argocdv1alpha1.ApplicationDestination{ | ||
Server: "https://kubernetes.default.svc", | ||
Namespace: "default", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed()) | ||
}) | ||
|
||
It("Should finally create a deployment status", func(ctx context.Context) { | ||
By("Setting up a deployment status endpoint") | ||
var deploymentStatus githubmock.DeploymentStatus | ||
githubServer.AddHandlers(map[string]http.Handler{ | ||
"GET /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.ListEndpoint(), | ||
"POST /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.CreateEndpoint(), | ||
}) | ||
|
||
By("Updating the application to running") | ||
startedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationRunning, | ||
StartedAt: startedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Consistently(func() int { return deploymentStatus.CreateCount() }, 100*time.Millisecond).Should(Equal(0)) | ||
|
||
By("Updating the deployment annotation") | ||
app.Annotations = map[string]string{ | ||
"argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/owner/repo-deployment/deployments/101", | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }, | ||
// This depends on requeueIntervalWhenDeploymentNotFound and takes longer time | ||
2*requeueIntervalWhenDeploymentNotFound, | ||
).Should(Equal(1)) | ||
|
||
By("Updating the application to succeeded") | ||
finishedAt := metav1.Now() | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationSucceeded, | ||
StartedAt: startedAt, | ||
FinishedAt: &finishedAt, | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
Eventually(func() int { return deploymentStatus.CreateCount() }, 3*time.Second).Should(Equal(2)) | ||
}, SpecTimeout(5*time.Second)) | ||
|
||
It("Should retry to create a deployment status until timeout", func(ctx context.Context) { | ||
By("Updating the application to running") | ||
app.Status.OperationState = &argocdv1alpha1.OperationState{ | ||
Phase: synccommon.OperationRunning, | ||
StartedAt: metav1.NewTime(metav1.Now().Add(-requeueTimeoutWhenDeploymentNotFound)), | ||
Operation: argocdv1alpha1.Operation{ | ||
Sync: &argocdv1alpha1.SyncOperation{ | ||
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | ||
}, | ||
}, | ||
} | ||
Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) | ||
|
||
By("Finding the retry event") | ||
Eventually(func(g Gomega) { | ||
var eventList corev1.EventList | ||
g.Expect(k8sClient.List(ctx, &eventList, crclient.MatchingFields{ | ||
"involvedObject.name": app.Name, | ||
"reason": "DeploymentNotFoundRetryTimeout", | ||
})).Should(Succeed()) | ||
g.Expect(eventList.Items).Should(HaveLen(1)) | ||
}) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.