From 11182f2d4a46d619610585ee113be906baf9681b Mon Sep 17 00:00:00 2001 From: phamnazage-jpg Date: Fri, 22 May 2026 14:27:41 +0800 Subject: [PATCH] feat(batch): add canonical v2 state enums --- internal/batch/types.go | 58 ++++++++++ internal/batch/types_test.go | 209 +++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 internal/batch/types.go create mode 100644 internal/batch/types_test.go diff --git a/internal/batch/types.go b/internal/batch/types.go new file mode 100644 index 00000000..0c8d1f17 --- /dev/null +++ b/internal/batch/types.go @@ -0,0 +1,58 @@ +package batch + +type RunState string + +const ( + RunStateRunning RunState = "running" + RunStateCompleted RunState = "completed" + RunStateCompletedWithWarnings RunState = "completed_with_warnings" + RunStateFailed RunState = "failed" + RunStateCancelled RunState = "cancelled" +) + +type ItemStage string + +const ( + ItemStageProbe ItemStage = "probe" + ItemStageProvision ItemStage = "provision" + ItemStageConfirm ItemStage = "confirm" + ItemStageValidate ItemStage = "validate" + ItemStageDone ItemStage = "done" +) + +type ConfirmationStatus string + +const ( + ConfirmationPending ConfirmationStatus = "pending" + ConfirmationConfirmed ConfirmationStatus = "confirmed" + ConfirmationAdvisory ConfirmationStatus = "advisory" + ConfirmationFailed ConfirmationStatus = "failed" +) + +type AccessStatus string + +const ( + AccessStatusUnknown AccessStatus = "unknown" + AccessStatusActive AccessStatus = "active" + AccessStatusDegraded AccessStatus = "degraded" + AccessStatusBroken AccessStatus = "broken" +) + +type MatchedAccountState string + +const ( + MatchedAccountStateNone MatchedAccountState = "none" + MatchedAccountStateActive MatchedAccountState = "active" + MatchedAccountStateDisabled MatchedAccountState = "disabled" + MatchedAccountStateDeprecated MatchedAccountState = "deprecated" + MatchedAccountStateBroken MatchedAccountState = "broken" +) + +type AccountResolution string + +const ( + AccountResolutionCreated AccountResolution = "created" + AccountResolutionReused AccountResolution = "reused" + AccountResolutionReactivated AccountResolution = "reactivated" + AccountResolutionReplaced AccountResolution = "replaced" +) diff --git a/internal/batch/types_test.go b/internal/batch/types_test.go new file mode 100644 index 00000000..1ed1cdf3 --- /dev/null +++ b/internal/batch/types_test.go @@ -0,0 +1,209 @@ +package batch + +import "testing" + +func TestRunStateConstants(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + got RunState + want string + }{ + {name: "running", got: RunStateRunning, want: "running"}, + {name: "completed", got: RunStateCompleted, want: "completed"}, + {name: "completed with warnings", got: RunStateCompletedWithWarnings, want: "completed_with_warnings"}, + {name: "failed", got: RunStateFailed, want: "failed"}, + {name: "cancelled", got: RunStateCancelled, want: "cancelled"}, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if string(tc.got) != tc.want { + t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want) + } + }) + } + + if isValidRunState(RunState("unexpected")) { + t.Fatal("isValidRunState(unexpected) = true, want false") + } +} + +func TestItemStateConstants(t *testing.T) { + t.Parallel() + + stageTests := []struct { + name string + got ItemStage + want string + }{ + {name: "probe", got: ItemStageProbe, want: "probe"}, + {name: "provision", got: ItemStageProvision, want: "provision"}, + {name: "confirm", got: ItemStageConfirm, want: "confirm"}, + {name: "validate", got: ItemStageValidate, want: "validate"}, + {name: "done", got: ItemStageDone, want: "done"}, + } + for _, tc := range stageTests { + tc := tc + t.Run("stage/"+tc.name, func(t *testing.T) { + t.Parallel() + if string(tc.got) != tc.want { + t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want) + } + }) + } + + confirmationTests := []struct { + name string + got ConfirmationStatus + want string + }{ + {name: "pending", got: ConfirmationPending, want: "pending"}, + {name: "confirmed", got: ConfirmationConfirmed, want: "confirmed"}, + {name: "advisory", got: ConfirmationAdvisory, want: "advisory"}, + {name: "failed", got: ConfirmationFailed, want: "failed"}, + } + for _, tc := range confirmationTests { + tc := tc + t.Run("confirmation/"+tc.name, func(t *testing.T) { + t.Parallel() + if string(tc.got) != tc.want { + t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want) + } + }) + } + + accessTests := []struct { + name string + got AccessStatus + want string + }{ + {name: "unknown", got: AccessStatusUnknown, want: "unknown"}, + {name: "active", got: AccessStatusActive, want: "active"}, + {name: "degraded", got: AccessStatusDegraded, want: "degraded"}, + {name: "broken", got: AccessStatusBroken, want: "broken"}, + } + for _, tc := range accessTests { + tc := tc + t.Run("access/"+tc.name, func(t *testing.T) { + t.Parallel() + if string(tc.got) != tc.want { + t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want) + } + }) + } + + matchedAccountStateTests := []struct { + name string + got MatchedAccountState + want string + }{ + {name: "none", got: MatchedAccountStateNone, want: "none"}, + {name: "active", got: MatchedAccountStateActive, want: "active"}, + {name: "disabled", got: MatchedAccountStateDisabled, want: "disabled"}, + {name: "deprecated", got: MatchedAccountStateDeprecated, want: "deprecated"}, + {name: "broken", got: MatchedAccountStateBroken, want: "broken"}, + } + for _, tc := range matchedAccountStateTests { + tc := tc + t.Run("matched-account/"+tc.name, func(t *testing.T) { + t.Parallel() + if string(tc.got) != tc.want { + t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want) + } + }) + } + + accountResolutionTests := []struct { + name string + got AccountResolution + want string + }{ + {name: "created", got: AccountResolutionCreated, want: "created"}, + {name: "reused", got: AccountResolutionReused, want: "reused"}, + {name: "reactivated", got: AccountResolutionReactivated, want: "reactivated"}, + {name: "replaced", got: AccountResolutionReplaced, want: "replaced"}, + } + for _, tc := range accountResolutionTests { + tc := tc + t.Run("account-resolution/"+tc.name, func(t *testing.T) { + t.Parallel() + if string(tc.got) != tc.want { + t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want) + } + }) + } + + if isValidItemStage(ItemStage("unexpected")) { + t.Fatal("isValidItemStage(unexpected) = true, want false") + } + if isValidConfirmationStatus(ConfirmationStatus("unexpected")) { + t.Fatal("isValidConfirmationStatus(unexpected) = true, want false") + } + if isValidAccessStatus(AccessStatus("unexpected")) { + t.Fatal("isValidAccessStatus(unexpected) = true, want false") + } + if isValidMatchedAccountState(MatchedAccountState("unexpected")) { + t.Fatal("isValidMatchedAccountState(unexpected) = true, want false") + } + if isValidAccountResolution(AccountResolution("unexpected")) { + t.Fatal("isValidAccountResolution(unexpected) = true, want false") + } +} + +func isValidRunState(state RunState) bool { + switch state { + case RunStateRunning, RunStateCompleted, RunStateCompletedWithWarnings, RunStateFailed, RunStateCancelled: + return true + default: + return false + } +} + +func isValidItemStage(stage ItemStage) bool { + switch stage { + case ItemStageProbe, ItemStageProvision, ItemStageConfirm, ItemStageValidate, ItemStageDone: + return true + default: + return false + } +} + +func isValidConfirmationStatus(status ConfirmationStatus) bool { + switch status { + case ConfirmationPending, ConfirmationConfirmed, ConfirmationAdvisory, ConfirmationFailed: + return true + default: + return false + } +} + +func isValidAccessStatus(status AccessStatus) bool { + switch status { + case AccessStatusUnknown, AccessStatusActive, AccessStatusDegraded, AccessStatusBroken: + return true + default: + return false + } +} + +func isValidMatchedAccountState(state MatchedAccountState) bool { + switch state { + case MatchedAccountStateNone, MatchedAccountStateActive, MatchedAccountStateDisabled, MatchedAccountStateDeprecated, MatchedAccountStateBroken: + return true + default: + return false + } +} + +func isValidAccountResolution(resolution AccountResolution) bool { + switch resolution { + case AccountResolutionCreated, AccountResolutionReused, AccountResolutionReactivated, AccountResolutionReplaced: + return true + default: + return false + } +}