@@ -16,6 +16,7 @@ import (
1616 mw "github.com/kernel/hypeman/lib/middleware"
1717 "github.com/kernel/hypeman/lib/oapi"
1818 "github.com/kernel/hypeman/lib/paths"
19+ restartpolicy "github.com/kernel/hypeman/lib/restart-policy"
1920 "github.com/kernel/hypeman/lib/system"
2021 "github.com/stretchr/testify/assert"
2122 "github.com/stretchr/testify/require"
@@ -281,6 +282,7 @@ func (m *captureUpdateManager) UpdateInstance(ctx context.Context, id string, re
281282 Env : req .Env ,
282283 AutoStandby : req .AutoStandby ,
283284 HealthCheck : req .HealthCheck ,
285+ RestartPolicy : req .RestartPolicy ,
284286 CreatedAt : now ,
285287 HypervisorType : hypervisor .TypeCloudHypervisor ,
286288 },
@@ -304,6 +306,7 @@ func (m *captureCreateManager) CreateInstance(ctx context.Context, req instances
304306 Vcpus : req .Vcpus ,
305307 AutoStandby : req .AutoStandby ,
306308 HealthCheck : req .HealthCheck ,
309+ RestartPolicy : req .RestartPolicy ,
307310 CreatedAt : now ,
308311 HypervisorType : hypervisor .TypeCloudHypervisor ,
309312 },
@@ -705,6 +708,48 @@ func TestCreateInstance_MapsHealthCheckPolicy(t *testing.T) {
705708 assert .Equal (t , oapi .InstanceHealthStatusStatusStarting , instance .HealthStatus .Status )
706709}
707710
711+ func TestCreateInstance_MapsRestartPolicy (t * testing.T ) {
712+ t .Parallel ()
713+
714+ svc := newTestService (t )
715+ origMgr := svc .InstanceManager
716+ mockMgr := & captureCreateManager {Manager : origMgr }
717+ svc .InstanceManager = mockMgr
718+
719+ policy := oapi .OnFailure
720+ backoff := "7s"
721+ stableAfter := "2m"
722+ maxAttempts := 4
723+
724+ resp , err := svc .CreateInstance (ctx (), oapi.CreateInstanceRequestObject {
725+ Body : & oapi.CreateInstanceRequest {
726+ Name : "test-restart-policy" ,
727+ Image : "docker.io/library/alpine:latest" ,
728+ RestartPolicy : & oapi.RestartPolicy {
729+ Policy : & policy ,
730+ Backoff : & backoff ,
731+ StableAfter : & stableAfter ,
732+ MaxAttempts : & maxAttempts ,
733+ },
734+ },
735+ })
736+ require .NoError (t , err )
737+
738+ created , ok := resp .(oapi.CreateInstance201JSONResponse )
739+ require .True (t , ok , "expected 201 response" )
740+ require .NotNil (t , mockMgr .lastReq )
741+ require .NotNil (t , mockMgr .lastReq .RestartPolicy )
742+ assert .Equal (t , restartpolicy .PolicyOnFailure , mockMgr .lastReq .RestartPolicy .Policy )
743+ assert .Equal (t , "7s" , mockMgr .lastReq .RestartPolicy .Backoff )
744+ assert .Equal (t , "2m0s" , mockMgr .lastReq .RestartPolicy .StableAfter )
745+ assert .Equal (t , 4 , mockMgr .lastReq .RestartPolicy .MaxAttempts )
746+
747+ instance := oapi .Instance (created )
748+ require .NotNil (t , instance .RestartPolicy )
749+ require .NotNil (t , instance .RestartPolicy .Policy )
750+ assert .Equal (t , oapi .OnFailure , * instance .RestartPolicy .Policy )
751+ }
752+
708753func TestUpdateInstance_MapsEnvPatch (t * testing.T ) {
709754 t .Parallel ()
710755 svc := newTestService (t )
@@ -883,6 +928,108 @@ func TestUpdateInstance_MapsHealthCheckPatch(t *testing.T) {
883928 assert .Equal (t , oapi .InstanceHealthStatusStatusUnknown , instance .HealthStatus .Status )
884929}
885930
931+ func TestUpdateInstance_MapsRestartPolicyPatch (t * testing.T ) {
932+ t .Parallel ()
933+ svc := newTestService (t )
934+
935+ origMgr := svc .InstanceManager
936+ now := time .Now ()
937+ mockMgr := & captureUpdateManager {
938+ Manager : origMgr ,
939+ result : & instances.Instance {
940+ StoredMetadata : instances.StoredMetadata {
941+ Id : "inst-update-restart-policy" ,
942+ Name : "inst-update-restart-policy" ,
943+ Image : "docker.io/library/alpine:latest" ,
944+ CreatedAt : now ,
945+ HypervisorType : hypervisor .TypeCloudHypervisor ,
946+ RestartPolicy : & restartpolicy.Policy {
947+ Policy : restartpolicy .PolicyAlways ,
948+ Backoff : "5s" ,
949+ StableAfter : "10m0s" ,
950+ },
951+ RestartStatus : restartpolicy.Status {
952+ BlockedReason : restartpolicy .BlockedReasonManualStop ,
953+ },
954+ },
955+ State : instances .StateStopped ,
956+ },
957+ }
958+ svc .InstanceManager = mockMgr
959+
960+ policy := oapi .Always
961+ resolved := & instances.Instance {
962+ StoredMetadata : instances.StoredMetadata {
963+ Id : "inst-update-restart-policy" ,
964+ Name : "inst-update-restart-policy" ,
965+ Image : "docker.io/library/alpine:latest" ,
966+ CreatedAt : now ,
967+ HypervisorType : hypervisor .TypeCloudHypervisor ,
968+ },
969+ State : instances .StateStopped ,
970+ }
971+
972+ resp , err := svc .UpdateInstance (mw .WithResolvedInstance (ctx (), resolved .Id , resolved ), oapi.UpdateInstanceRequestObject {
973+ Id : resolved .Id ,
974+ Body : & oapi.UpdateInstanceRequest {
975+ RestartPolicy : & oapi.RestartPolicy {Policy : & policy },
976+ },
977+ })
978+ require .NoError (t , err )
979+ updated , ok := resp .(oapi.UpdateInstance200JSONResponse )
980+ require .True (t , ok , "expected 200 response" )
981+
982+ require .NotNil (t , mockMgr .lastReq )
983+ assert .True (t , mockMgr .lastReq .RestartPolicySet )
984+ require .NotNil (t , mockMgr .lastReq .RestartPolicy )
985+ assert .Equal (t , restartpolicy .PolicyAlways , mockMgr .lastReq .RestartPolicy .Policy )
986+
987+ instance := oapi .Instance (updated )
988+ require .NotNil (t , instance .RestartPolicy )
989+ require .NotNil (t , instance .RestartStatus )
990+ require .NotNil (t , instance .RestartStatus .BlockedReason )
991+ assert .Equal (t , oapi .ManualStop , * instance .RestartStatus .BlockedReason )
992+ }
993+
994+ func TestUpdateInstance_RejectsInvalidRestartPolicy (t * testing.T ) {
995+ t .Parallel ()
996+ svc := newTestService (t )
997+
998+ origMgr := svc .InstanceManager
999+ mockMgr := & captureUpdateManager {Manager : origMgr }
1000+ svc .InstanceManager = mockMgr
1001+
1002+ now := time .Now ()
1003+ resolved := & instances.Instance {
1004+ StoredMetadata : instances.StoredMetadata {
1005+ Id : "inst-update-restart-policy" ,
1006+ Name : "inst-update-restart-policy" ,
1007+ Image : "docker.io/library/alpine:latest" ,
1008+ CreatedAt : now ,
1009+ HypervisorType : hypervisor .TypeCloudHypervisor ,
1010+ },
1011+ State : instances .StateStopped ,
1012+ }
1013+ policy := oapi .OnFailure
1014+ backoff := "0s"
1015+
1016+ resp , err := svc .UpdateInstance (mw .WithResolvedInstance (ctx (), resolved .Id , resolved ), oapi.UpdateInstanceRequestObject {
1017+ Id : resolved .Id ,
1018+ Body : & oapi.UpdateInstanceRequest {
1019+ RestartPolicy : & oapi.RestartPolicy {
1020+ Policy : & policy ,
1021+ Backoff : & backoff ,
1022+ },
1023+ },
1024+ })
1025+ require .NoError (t , err )
1026+
1027+ badReq , ok := resp .(oapi.UpdateInstance400JSONResponse )
1028+ require .True (t , ok , "expected 400 response" )
1029+ assert .Equal (t , "invalid_restart_policy" , badReq .Code )
1030+ assert .Nil (t , mockMgr .lastReq )
1031+ }
1032+
8861033func TestUpdateInstance_RejectsZeroAutoStandbyIgnoreDestinationPort (t * testing.T ) {
8871034 t .Parallel ()
8881035 svc := newTestService (t )
0 commit comments