Skip to content

Commit e958013

Browse files
committed
Added int test for sync commands
1 parent e511e8d commit e958013

File tree

6 files changed

+162
-23
lines changed

6 files changed

+162
-23
lines changed

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ SHELL := bash
88
MAKEFLAGS += --warn-undefined-variables
99
MAKEFLAGS += --no-builtin-rules
1010
CL_HOME := `pwd`
11+
INPUT := $(word 2,$(MAKECMDGOALS))
1112

1213
.DEFAULT_GOAL := help
1314
ifeq ($(origin .RECIPEPREFIX), undefined)
@@ -16,7 +17,7 @@ endif
1617
.RECIPEPREFIX = >
1718
TAG :=
1819

19-
.PHONY: help test unit int release
20+
.PHONY: help test unit int release int_single
2021

2122
help: ## Display this help section
2223
> @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {printf "\033[36m%-38s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
@@ -38,10 +39,12 @@ covunit: ## Run unit tests with coverage
3839
> go tool covdata textfmt -i=$(CL_HOME)/coverage/unit -o $(CL_HOME)/coverage/profile
3940
> go tool cover -func coverage/profile
4041

41-
4242
int: ## Run integration tests
4343
> CL_HOME=$(CL_HOME) ./tests/run_cli_tests.sh
4444

45+
int_single: ## Run one integration test
46+
> CL_SINGLE_TEST=${INPUT} CL_HOME=$(CL_HOME) ./tests/run_cli_tests.sh
47+
4548
covint: ## Run integration tests with coverage
4649
> rm -rf $(CL_HOME)/coverage/int && mkdir -p $(CL_HOME)/coverage/int
4750
> rm -rf $(CL_HOME)/coverage/client && mkdir -p $(CL_HOME)/coverage/client

cmd/clace/sync_cmds.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func initSyncCommand(commonFlags []cli.Flag, clientConfig *types.ClientConfig) *
2222
Usage: "Manage sync operations, scheduled and webhook",
2323
Subcommands: []*cli.Command{
2424
syncScheduleCommand(commonFlags, clientConfig),
25+
syncRunCommand(commonFlags, clientConfig),
2526
syncListCommand(commonFlags, clientConfig),
2627
syncDeleteCommand(commonFlags, clientConfig),
2728
},
@@ -92,6 +93,10 @@ Examples:
9293
return err
9394
}
9495

96+
if syncResponse.SyncJobStatus.Error != "" {
97+
return fmt.Errorf("error creating sync job: %s", syncResponse.SyncJobStatus.Error)
98+
}
99+
95100
printApplyResponse(cCtx, &syncResponse.SyncJobStatus.ApplyResponse)
96101

97102
fmt.Printf("\nSync job created with Id: %s\n", syncResponse.Id)
@@ -140,6 +145,50 @@ func syncListCommand(commonFlags []cli.Flag, clientConfig *types.ClientConfig) *
140145
}
141146
}
142147

148+
func syncRunCommand(commonFlags []cli.Flag, clientConfig *types.ClientConfig) *cli.Command {
149+
flags := make([]cli.Flag, 0, len(commonFlags)+2)
150+
flags = append(flags, commonFlags...)
151+
flags = append(flags, dryRunFlag())
152+
153+
return &cli.Command{
154+
Name: "run",
155+
Usage: "Run specified sync job",
156+
Flags: flags,
157+
Before: altsrc.InitInputSourceWithContext(flags, altsrc.NewTomlSourceFromFlagFunc(configFileFlagName)),
158+
ArgsUsage: "args: <syncId>",
159+
UsageText: `
160+
Examples:
161+
Run sync job: clace sync run cl_sync_44asd232`,
162+
Action: func(cCtx *cli.Context) error {
163+
if cCtx.NArg() != 1 {
164+
return fmt.Errorf("expected one args: <syncId>")
165+
}
166+
167+
client := system.NewHttpClient(clientConfig.ServerUri, clientConfig.AdminUser, clientConfig.Client.AdminPassword, clientConfig.Client.SkipCertCheck)
168+
values := url.Values{}
169+
values.Add("id", cCtx.Args().First())
170+
values.Add(DRY_RUN_ARG, strconv.FormatBool(cCtx.Bool(DRY_RUN_FLAG)))
171+
172+
var response types.SyncJobStatus
173+
err := client.Post("/_clace/sync/run", values, nil, &response)
174+
if err != nil {
175+
return err
176+
}
177+
178+
if response.Error != "" {
179+
return fmt.Errorf("error running sync job: %s", response.Error)
180+
}
181+
182+
printApplyResponse(cCtx, &response.ApplyResponse)
183+
if response.ApplyResponse.DryRun {
184+
fmt.Print(DRY_RUN_MESSAGE)
185+
}
186+
187+
return nil
188+
},
189+
}
190+
}
191+
143192
func syncDeleteCommand(commonFlags []cli.Flag, clientConfig *types.ClientConfig) *cli.Command {
144193
flags := make([]cli.Flag, 0, len(commonFlags)+2)
145194
flags = append(flags, commonFlags...)

internal/server/router.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,24 @@ func (h *Handler) createSyncEntry(r *http.Request) (any, error) {
10241024
return results, nil
10251025
}
10261026

1027+
func (h *Handler) runSyncEntry(r *http.Request) (any, error) {
1028+
id := r.URL.Query().Get("id")
1029+
dryRun, err := parseBoolArg(r.URL.Query().Get(DRY_RUN_ARG), false)
1030+
if err != nil {
1031+
return nil, err
1032+
}
1033+
1034+
updateTargetInContext(r, id, dryRun)
1035+
updateOperationInContext(r, "sync_run")
1036+
1037+
results, err := h.server.RunSync(r.Context(), id, dryRun)
1038+
if err != nil {
1039+
return nil, types.CreateRequestError(err.Error(), http.StatusBadRequest)
1040+
}
1041+
1042+
return results, nil
1043+
}
1044+
10271045
func (h *Handler) deleteSyncEntry(r *http.Request) (any, error) {
10281046
id := r.URL.Query().Get("id")
10291047
if id == "" {
@@ -1162,17 +1180,22 @@ func (h *Handler) serveInternal(enableBasicAuth bool) http.Handler {
11621180

11631181
// API to create sync entry
11641182
r.Post("/sync", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1165-
h.apiHandler(w, r, enableBasicAuth, "apply", h.createSyncEntry)
1183+
h.apiHandler(w, r, enableBasicAuth, "sync_create", h.createSyncEntry)
1184+
}))
1185+
1186+
// API to run sync
1187+
r.Post("/sync/run", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1188+
h.apiHandler(w, r, enableBasicAuth, "sync_run", h.runSyncEntry)
11661189
}))
11671190

11681191
// API to delete sync entry
11691192
r.Delete("/sync", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1170-
h.apiHandler(w, r, enableBasicAuth, "apply", h.deleteSyncEntry)
1193+
h.apiHandler(w, r, enableBasicAuth, "sync_delete", h.deleteSyncEntry)
11711194
}))
11721195

11731196
// API to get sync entries
11741197
r.Get("/sync", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1175-
h.apiHandler(w, r, enableBasicAuth, "apply", h.listSyncEntries)
1198+
h.apiHandler(w, r, enableBasicAuth, "list_sync", h.listSyncEntries)
11761199
}))
11771200

11781201
return r

internal/server/sync.go

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (s *Server) CreateSyncEntry(ctx context.Context, path string, scheduled, dr
5454
return nil, err
5555
}
5656

57-
syncStatus, updatedApps, err := s.runSyncJob(ctx, tx, &syncEntry, true, nil)
57+
syncStatus, updatedApps, err := s.runSyncJob(ctx, tx, &syncEntry, dryRun, true, nil)
5858
if err != nil {
5959
return nil, err
6060
}
@@ -72,15 +72,38 @@ func (s *Server) CreateSyncEntry(ctx context.Context, path string, scheduled, dr
7272
SyncJobStatus: *syncStatus,
7373
}
7474

75-
if dryRun {
76-
return &ret, nil
75+
if err := s.CompleteTransaction(ctx, tx, updatedApps, dryRun, "create_sync"); err != nil {
76+
return nil, err
7777
}
7878

79-
if err := s.CompleteTransaction(ctx, tx, updatedApps, false, "create_sync"); err != nil {
79+
return &ret, nil
80+
}
81+
82+
func (s *Server) RunSync(ctx context.Context, id string, dryRun bool) (*types.SyncJobStatus, error) {
83+
tx, err := s.db.BeginTransaction(ctx)
84+
if err != nil {
8085
return nil, err
8186
}
87+
defer tx.Rollback()
8288

83-
return &ret, nil
89+
syncEntry, err := s.db.GetSyncEntry(ctx, tx, id)
90+
if err != nil {
91+
return nil, err
92+
}
93+
94+
syncStatus, updatedApps, err := s.runSyncJob(ctx, tx, syncEntry, dryRun, true, nil)
95+
if err != nil {
96+
return nil, err
97+
}
98+
if syncStatus.Error != "" {
99+
// The sync job job failed, status would be already updated
100+
return nil, errors.New(syncStatus.Error)
101+
}
102+
103+
if err := s.CompleteTransaction(ctx, tx, updatedApps, dryRun, "sync_run"); err != nil {
104+
return nil, err
105+
}
106+
return syncStatus, nil
84107
}
85108

86109
func (s *Server) DeleteSyncEntry(ctx context.Context, id string, dryRun bool) (*types.SyncDeleteResponse, error) {
@@ -177,7 +200,7 @@ func (s *Server) runSyncJobs() error {
177200
continue
178201
}
179202

180-
_, _, err = s.runSyncJob(ctx, types.Transaction{}, entry, true, repoCache) // each sync runs in its own transaction
203+
_, _, err = s.runSyncJob(ctx, types.Transaction{}, entry, false, true, repoCache) // each sync runs in its own transaction
181204
if err != nil {
182205
s.Error().Err(err).Msgf("Error running sync job %s", entry.Id)
183206
// One failure does not stop the rest
@@ -188,7 +211,7 @@ func (s *Server) runSyncJobs() error {
188211
}
189212

190213
func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entry *types.SyncEntry,
191-
checkCommitHash bool, repoCache *RepoCache) (*types.SyncJobStatus, []types.AppPathDomain, error) {
214+
dryRun, checkCommitHash bool, repoCache *RepoCache) (*types.SyncJobStatus, []types.AppPathDomain, error) {
192215
var tx types.Transaction
193216
var err error
194217
if inputTx.Tx == nil {
@@ -218,7 +241,7 @@ func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entr
218241
lastRunCommitId = entry.Status.CommitId
219242
}
220243

221-
applyInfo, updatedApps, applyErr := s.Apply(ctx, tx, entry.Path, "all", entry.Metadata.Approve, false, entry.Metadata.Promote, types.AppReloadOption(entry.Metadata.Reload),
244+
applyInfo, updatedApps, applyErr := s.Apply(ctx, tx, entry.Path, "all", entry.Metadata.Approve, dryRun, entry.Metadata.Promote, types.AppReloadOption(entry.Metadata.Reload),
222245
entry.Metadata.GitBranch, "", entry.Metadata.GitAuth, entry.Metadata.Clobber, entry.Metadata.ForceReload, lastRunCommitId, repoCache)
223246

224247
status := types.SyncJobStatus{
@@ -230,6 +253,7 @@ func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entr
230253
s.Error().Err(applyErr).Msgf("Error applying sync job %s", entry.Id)
231254
status.Error = applyErr.Error()
232255
applyInfo = &types.AppApplyResponse{}
256+
applyInfo.DryRun = dryRun
233257
applyInfo.FilteredApps = lastRunApps
234258
status.FailureCount = entry.Status.FailureCount + 1
235259
if status.FailureCount >= s.config.System.MaxSyncFailureCount {
@@ -242,7 +266,6 @@ func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entr
242266
status.FailureCount = 0
243267
}
244268

245-
status.ApplyResponse = *applyInfo
246269
reloadResults := make([]types.AppPathDomain, 0, len(lastRunApps))
247270
approveResults := make([]types.ApproveResult, 0, len(lastRunApps))
248271
promoteResults := make([]types.AppPathDomain, 0, len(lastRunApps))
@@ -273,7 +296,7 @@ func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entr
273296
if !checkCommitHash {
274297
return nil, nil, fmt.Errorf("Unexpected error, sync rerun with no commit hash")
275298
}
276-
return s.runSyncJob(ctx, inputTx, entry, false, repoCache)
299+
return s.runSyncJob(ctx, inputTx, entry, dryRun, false, repoCache)
277300
} else {
278301
var reloadErr error
279302
for _, appPath := range lastRunApps {
@@ -301,9 +324,9 @@ func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entr
301324
}
302325

303326
if reloadErr != nil {
304-
status.ApplyResponse.ReloadResults = reloadResults
305-
status.ApplyResponse.ApproveResults = approveResults
306-
status.ApplyResponse.PromoteResults = promoteResults
327+
applyInfo.ReloadResults = reloadResults
328+
applyInfo.ApproveResults = approveResults
329+
applyInfo.PromoteResults = promoteResults
307330
}
308331
}
309332
}
@@ -320,13 +343,14 @@ func (s *Server) runSyncJob(ctx context.Context, inputTx types.Transaction, entr
320343
updatedApps = nil
321344
}
322345

346+
status.ApplyResponse = *applyInfo
323347
err = s.db.UpdateSyncStatus(ctx, tx, entry.Id, &status)
324348
if err != nil {
325349
return nil, nil, err
326350
}
327351

328352
if status.Error == "" && inputTx.Tx == nil {
329-
if err := s.CompleteTransaction(ctx, tx, updatedApps, false, "sync"); err != nil {
353+
if err := s.CompleteTransaction(ctx, tx, updatedApps, dryRun, "sync"); err != nil {
330354
return nil, nil, err
331355
}
332356
}

tests/commander/test_sync.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
config:
2+
env:
3+
CL_CONFIG_FILE: clace.toml
4+
GOCOVERDIR: ${GOCOVERDIR}/../client
5+
PATH: ${PATH}
6+
tests:
7+
sync0001: ## setup
8+
command: ../clace sync schedule --approve --promote github.com/claceio/clace/examples/utils.star
9+
stdout: "Sync job created with Id"
10+
sync0010:
11+
command: ../clace sync list
12+
stdout:
13+
line-count: 2
14+
contains:
15+
- "examples/utils.star"
16+
sync0020:
17+
command: ../clace sync list -f json | jq -r '.[0].id' > sync_test_id.tmp
18+
sync0030:
19+
command: sh -c 'id=$(cat sync_test_id.tmp); ../clace sync run "$id"'
20+
stdout: "0 app(s) created, 0 app(s) updated, 0 app(s) reloaded, 0 app(s) skipped, 0 app(s) approved, 0 app(s) promoted"
21+
sync0040:
22+
command: ../clace app delete /utils/disk_usage
23+
exit-code: 0
24+
sync0050:
25+
command: sh -c 'id=$(cat sync_test_id.tmp); ../clace sync run "$id"'
26+
stdout: "1 app(s) created, 0 app(s) updated, 2 app(s) reloaded, 5 app(s) skipped, 0 app(s) approved, 1 app(s) promoted"
27+
sync0060:
28+
command: sh -c 'id=$(cat sync_test_id.tmp); ../clace sync delete "$id"'
29+
stdout: "deleted"
30+
sync0070:
31+
command: ../clace sync list
32+
stdout:
33+
line-count: 1

tests/run_cli_tests.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ admin_password = "abcd"
100100
skip_cert_check = true
101101
EOF
102102

103-
commander test $CL_TEST_VERBOSE test_basics.yaml
103+
if [[ -z $CL_SINGLE_TEST ]]; then
104+
commander test $CL_TEST_VERBOSE test_basics.yaml
105+
fi
104106
CL_CONFIG_FILE=config_basic_test.toml GOCOVERDIR=$GOCOVERDIR/../client ../clace server stop
105107
rm -rf metadata run/clace.sock config_basic_*.toml
106108

@@ -177,8 +179,13 @@ export TESTENV=abc
177179
export c1c2_c3=xyz
178180
GOCOVERDIR=$GOCOVERDIR ../clace server start &
179181
sleep 2
180-
commander test $CL_TEST_VERBOSE --dir ./commander/
181-
#commander test $CL_TEST_VERBOSE ./commander/test_misc.yaml
182+
183+
if [[ -z $CL_SINGLE_TEST ]]; then
184+
commander test $CL_TEST_VERBOSE --dir ./commander/
185+
else
186+
commander test $CL_TEST_VERBOSE ./commander/$CL_SINGLE_TEST
187+
CL_CONTAINER_COMMANDS="disable"
188+
fi
182189

183190
echo $?
184191

@@ -230,4 +237,4 @@ EOF
230237
done
231238

232239
cleanup
233-
echo "Test completed"
240+
echo "Test $CL_SINGLE_TEST completed"

0 commit comments

Comments
 (0)