Skip to content

Commit b13129e

Browse files
authored
Add Sync Status and Latest Deployment Time (#751, #879) (#21)
Signed-off-by: Keith Chong <[email protected]>
1 parent 3f074ec commit b13129e

File tree

8 files changed

+145
-8
lines changed

8 files changed

+145
-8
lines changed

.github/workflows/golangci-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ jobs:
1616
- name: golangci-lint
1717
uses: golangci/golangci-lint-action@v2
1818
with:
19-
version: v1.34
19+
version: v1.37
2020
only-new-issues: true

.golangci.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
run:
2+
timeout: 10m

pkg/httpapi/api_test.go

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net/url"
1212
"strings"
1313
"testing"
14+
"time"
1415

1516
argoV1aplha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
1617
gogit "github.com/go-git/go-git/v5"
@@ -308,7 +309,7 @@ func TestListApplications(t *testing.T) {
308309
})
309310

310311
var createOptions []ctrlclient.CreateOption
311-
app, _ := testArgoApplication()
312+
app, _ := testArgoApplication("testdata/application.yaml")
312313
err = kc.Create(context.TODO(), app, createOptions...)
313314
if err != nil {
314315
t.Fatal(err)
@@ -321,12 +322,62 @@ func TestListApplications(t *testing.T) {
321322
t.Fatal(err)
322323
}
323324

325+
assertJSONResponse(t, res, map[string]interface{}{
326+
"applications": []interface{}{
327+
map[string]interface{}{
328+
"name": "test-app",
329+
"repo_url": "https://github.com/test-repo/gitops.git",
330+
"environments": []interface{}{"dev"},
331+
"sync_status": []interface{}{"Synced"},
332+
"last_deployed": []interface{}{time.Date(2021, time.Month(5), 15, 2, 12, 13, 0, time.UTC).Local().String()},
333+
},
334+
},
335+
})
336+
}
337+
338+
func TestListApplicationsWIthTwoApps(t *testing.T) {
339+
err := argoV1aplha1.AddToScheme(scheme.Scheme)
340+
if err != nil {
341+
t.Fatal(err)
342+
}
343+
344+
builder := fake.NewClientBuilder()
345+
kc := builder.Build()
346+
347+
ts, _ := makeServer(t, func(router *APIRouter) {
348+
router.k8sClient = kc
349+
})
350+
351+
var createOptions []ctrlclient.CreateOption
352+
app, _ := testArgoApplication("testdata/application.yaml")
353+
err = kc.Create(context.TODO(), app, createOptions...)
354+
if err != nil {
355+
t.Fatal(err)
356+
}
357+
358+
app2, _ := testArgoApplication("testdata/application2.yaml")
359+
err = kc.Create(context.TODO(), app2, createOptions...)
360+
if err != nil {
361+
t.Fatal(err)
362+
}
363+
364+
url := "https://github.com/test-repo/gitops.git?ref=HEAD"
365+
req := makeClientRequest(t, "Bearer testing", fmt.Sprintf("%s/applications?url=%s", ts.URL, url))
366+
res, err := ts.Client().Do(req)
367+
if err != nil {
368+
t.Fatal(err)
369+
}
370+
324371
assertJSONResponse(t, res, map[string]interface{}{
325372
"applications": []interface{}{
326373
map[string]interface{}{
327374
"name": "test-app",
328375
"repo_url": "https://github.com/test-repo/gitops.git",
329-
"environments": []interface{}{"dev"},
376+
"environments": []interface{}{"dev", "production"},
377+
"sync_status": []interface{}{"Synced", "OutOfSync"},
378+
"last_deployed": []interface{}{time.Date(2021, time.Month(5), 15, 2, 12, 13, 0, time.UTC).Local().String(),
379+
time.Date(2021, time.Month(5), 16, 1, 10, 35, 0, time.UTC).Local().String(),
380+
},
330381
},
331382
},
332383
})
@@ -349,8 +400,8 @@ func TestListApplications_badURL(t *testing.T) {
349400
assertHTTPError(t, resp, http.StatusBadRequest, "please provide a valid GitOps repo URL")
350401
}
351402

352-
func testArgoApplication() (*argoV1aplha1.Application, error) {
353-
applicationYaml, _ := ioutil.ReadFile("testdata/application.yaml")
403+
func testArgoApplication(appCr string) (*argoV1aplha1.Application, error) {
404+
applicationYaml, _ := ioutil.ReadFile(appCr)
354405
app := &argoV1aplha1.Application{}
355406
err := yaml.Unmarshal(applicationYaml, app)
356407
if err != nil {

pkg/httpapi/conversion.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package httpapi
22

33
import (
44
log "github.com/sirupsen/logrus"
5+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
56
"sort"
67
"strings"
78

@@ -50,14 +51,27 @@ func applicationsToAppsResponse(appSet []*argoV1aplha1.Application, repoURL stri
5051
continue
5152
}
5253

54+
var lastDeployed metav1.Time
55+
size := len(app.Status.History)
56+
if size > 0 {
57+
lastDeployed = app.Status.History[size-1].DeployedAt
58+
}
59+
var lastDeployedTime = lastDeployed.String()
60+
if lastDeployed.IsZero() {
61+
lastDeployedTime = ""
62+
}
5363
if appResp, ok := appsMap[appName]; !ok {
5464
appsMap[appName] = appResponse{
5565
Name: appName,
5666
RepoURL: app.Spec.Source.RepoURL,
5767
Environments: []string{app.Spec.Destination.Namespace},
68+
SyncStatus: []string{string(app.Status.Sync.Status)},
69+
LastDeployed: []string{lastDeployedTime},
5870
}
5971
} else {
6072
appResp.Environments = append(appResp.Environments, app.Spec.Destination.Namespace)
73+
appResp.SyncStatus = append(appResp.SyncStatus, string(app.Status.Sync.Status))
74+
appResp.LastDeployed = append(appResp.LastDeployed, lastDeployed.String())
6175
appsMap[appName] = appResp
6276
}
6377
}

pkg/httpapi/conversion_test.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
argoV1aplha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
66
"testing"
7+
"time"
78

89
"github.com/google/go-cmp/cmp"
910
)
@@ -18,6 +19,8 @@ func TestPipelinesToAppsResponse(t *testing.T) {
1819
{
1920
Name: "taxi", RepoURL: "https://example.com/demo/gitops.git",
2021
Environments: []string{"dev"},
22+
SyncStatus: nil,
23+
LastDeployed: nil,
2124
},
2225
},
2326
}
@@ -28,12 +31,51 @@ func TestPipelinesToAppsResponse(t *testing.T) {
2831

2932
func TestApplicationsToAppsResponse(t *testing.T) {
3033
var apps []*argoV1aplha1.Application
31-
app, _ := testArgoApplication()
34+
app, _ := testArgoApplication("testdata/application.yaml")
3235
apps = append(apps, app)
3336

3437
want := &appsResponse{
3538
Apps: []appResponse{
36-
{Name: "test-app", RepoURL: "https://github.com/test-repo/gitops.git", Environments: []string{"dev"}},
39+
{
40+
Name: "test-app",
41+
RepoURL: "https://github.com/test-repo/gitops.git",
42+
Environments: []string{"dev"},
43+
SyncStatus: []string{"Synced"},
44+
LastDeployed: []string{time.Date(2021, time.Month(5), 15, 2, 12, 13, 0, time.UTC).Local().String()},
45+
},
46+
},
47+
}
48+
49+
resp := applicationsToAppsResponse(apps, "https://github.com/test-repo/gitops")
50+
51+
if diff := cmp.Diff(want, resp); diff != "" {
52+
t.Fatal(fmt.Errorf("WANT[%v] != RECEIVED[%v], diff=%s", want, resp, diff))
53+
}
54+
55+
resp = applicationsToAppsResponse(apps, "https://github.com/test-repo/gitops.git")
56+
57+
if diff := cmp.Diff(want, resp); diff != "" {
58+
t.Fatal(fmt.Errorf("WANT[%v] != RECEIVED[%v], diff=%s", want, resp, diff))
59+
}
60+
}
61+
62+
func TestApplicationsToAppsResponseForTwoApps(t *testing.T) {
63+
var apps []*argoV1aplha1.Application
64+
app, _ := testArgoApplication("testdata/application.yaml")
65+
apps = append(apps, app)
66+
app2, _ := testArgoApplication("testdata/application2.yaml")
67+
apps = append(apps, app2)
68+
69+
want := &appsResponse{
70+
Apps: []appResponse{
71+
{
72+
Name: "test-app",
73+
RepoURL: "https://github.com/test-repo/gitops.git",
74+
Environments: []string{"dev", "production"},
75+
SyncStatus: []string{"Synced", "OutOfSync"},
76+
LastDeployed: []string{time.Date(2021, time.Month(5), 15, 2, 12, 13, 0, time.UTC).Local().String(),
77+
time.Date(2021, time.Month(5), 16, 1, 10, 35, 0, time.UTC).Local().String()},
78+
},
3779
},
3880
}
3981

pkg/httpapi/manifest.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ type appResponse struct {
44
Name string `json:"name,omitempty"`
55
RepoURL string `json:"repo_url,omitempty"`
66
Environments []string `json:"environments,omitempty"`
7+
SyncStatus []string `json:"sync_status,omitempty"`
8+
LastDeployed []string `json:"last_deployed,omitempty"`
79
}
810

911
type appsResponse struct {

pkg/httpapi/testdata/application.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@ spec:
1212
project: default
1313
source:
1414
path: environments/dev/apps/app-taxi/overlays
15-
repoURL: https://github.com/test-repo/gitops.git
15+
repoURL: https://github.com/test-repo/gitops.git
16+
status:
17+
history:
18+
- deployedAt: "2021-05-15T02:12:13Z"
19+
sync:
20+
status: Synced
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: argoproj.io/v1alpha1
2+
kind: Application
3+
metadata:
4+
labels:
5+
app.kubernetes.io/name: test-app
6+
name: production-test-app
7+
namespace: test-namespace
8+
spec:
9+
destination:
10+
namespace: production
11+
server: https://kubernetes.default.svc
12+
project: default
13+
source:
14+
path: environments/production/apps/app-taxi/overlays
15+
repoURL: https://github.com/test-repo/gitops.git
16+
status:
17+
history:
18+
- deployedAt: "2021-05-10T01:10:35Z"
19+
- deployedAt: "2021-05-16T01:10:35Z"
20+
sync:
21+
status: OutOfSync

0 commit comments

Comments
 (0)