1111// express or implied. See the License for the specific language governing
1212// permissions and limitations under the License.
1313
14- // Use this file to add custom implementation for any operation of intercept
15- // the autogenerated code that trigger an update on an endpoint
14+ // Use this file if the Status/Spec of the CR needs to be modified after
15+ // create/describe/ update operation
1616
1717package endpoint
1818
1919import (
2020 "context"
21- "errors"
2221 "strings"
2322
2423 ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
25- "github.com/aws-controllers-k8s/runtime/pkg/requeue"
24+ svcapitypes "github.com/aws-controllers-k8s/sagemaker-controller/apis/v1alpha1"
25+ svccommon "github.com/aws-controllers-k8s/sagemaker-controller/pkg/common"
26+ "github.com/aws/aws-sdk-go/aws"
2627 "github.com/aws/aws-sdk-go/aws/awserr"
2728 svcsdk "github.com/aws/aws-sdk-go/service/sagemaker"
2829)
2930
3031var (
32+ modifyingStatuses = []string {
33+ svcsdk .EndpointStatusCreating ,
34+ svcsdk .EndpointStatusUpdating ,
35+ svcsdk .EndpointStatusSystemUpdating ,
36+ svcsdk .EndpointStatusRollingBack ,
37+ svcsdk .EndpointStatusDeleting ,
38+ }
39+
40+ resourceName = resourceGK .Kind
41+
3142 FailUpdateError = awserr .New ("EndpointUpdateError" , "unable to update endpoint. check FailureReason" , nil )
3243
3344 FailureReasonInternalServiceErrorPrefix = "Request to service failed"
3445)
3546
36- // customUpdateEndpoint adds specialized logic to check if controller should
47+ // customDescribeEndpointSetOutput sets the resource ResourceSynced condition to False if endpoint is
48+ // being modified by AWS
49+ func (rm * resourceManager ) customDescribeEndpointSetOutput (
50+ resp * svcsdk.DescribeEndpointOutput ,
51+ ko * svcapitypes.Endpoint ,
52+ ) {
53+ // Workaround: Field config for LatestEndpointConfigName of generator config
54+ // does not code generate this correctly since this field is part of Spec
55+ // SageMaker users will need following information:
56+ // - latestEndpointConfig
57+ // - desiredEndpointConfig
58+ // - LastEndpointConfigNameForUpdate
59+ // - FailureReason
60+ // to determine the correct course of action in case of update to Endpoint fails
61+ if resp .EndpointConfigName != nil {
62+ ko .Status .LatestEndpointConfigName = resp .EndpointConfigName
63+ } else {
64+ ko .Status .LatestEndpointConfigName = nil
65+ }
66+
67+ svccommon .SetSyncedCondition (& resource {ko }, resp .EndpointStatus , & resourceName , & modifyingStatuses )
68+ }
69+
70+ // customUpdateEndpointSetOutput sets the resource ResourceSynced condition to False if endpoint is
71+ // being updated. At this stage we know call to updateEndpoint was successful.
72+ func (rm * resourceManager ) customUpdateEndpointSetOutput (ko * svcapitypes.Endpoint ) {
73+ // no nil check present here since Spec.EndpointConfigName is a required field
74+ ko .Status .LastEndpointConfigNameForUpdate = ko .Spec .EndpointConfigName
75+ // injecting Updating status to keep the Sync condition message and status.endpointStatus in sync
76+ ko .Status .EndpointStatus = aws .String (svcsdk .EndpointStatusUpdating )
77+
78+ svccommon .SetSyncedCondition (& resource {ko }, ko .Status .EndpointStatus , & resourceName , & modifyingStatuses )
79+ }
80+
81+ // customUpdateEndpointPreChecks adds specialized logic to check if controller should
3782// proceeed with updateEndpoint call.
3883// Update is blocked in the following cases:
39- // 1. while EndpointStatus != InService
84+ // 1. while EndpointStatus != InService (handled by requeueUntilCanModify method)
4085// 2. EndpointStatus == Failed
4186// 3. A previous update to the Endpoint with same endpointConfigName failed
4287// Method returns nil if endpoint can be updated, otherwise error depending on above cases
43- func (rm * resourceManager ) customUpdateEndpoint (
88+ func (rm * resourceManager ) customUpdateEndpointPreChecks (
4489 ctx context.Context ,
4590 desired * resource ,
4691 latest * resource ,
4792 delta * ackcompare.Delta ,
48- ) ( * resource , error ) {
93+ ) error {
4994 latestStatus := latest .ko .Status .EndpointStatus
5095 if latestStatus == nil {
51- return nil , nil
52- }
53-
54- if * latestStatus != svcsdk .EndpointStatusFailed {
55- // Case 1 - requeueAfter until endpoint is in InService state
56- err := rm .endpointStatusAllowUpdates (ctx , latest )
57- if err != nil {
58- return nil , err
59- }
96+ return nil
6097 }
6198
6299 failureReason := latest .ko .Status .FailureReason
63- latestEndpointConfig := latest .ko .Spec .EndpointConfigName
64100 desiredEndpointConfig := desired .ko .Spec .EndpointConfigName
65101 lastEndpointConfigForUpdate := desired .ko .Status .LastEndpointConfigNameForUpdate
66102
@@ -72,7 +108,7 @@ func (rm *resourceManager) customUpdateEndpoint(
72108 // "Request to service failed" means update failed because of ISE and can be retried
73109 (failureReason != nil && lastEndpointConfigForUpdate != nil &&
74110 ! strings .HasPrefix (* failureReason , FailureReasonInternalServiceErrorPrefix ) &&
75- * desiredEndpointConfig != * latestEndpointConfig &&
111+ delta . DifferentAt ( "Spec.EndpointConfigName" ) &&
76112 * desiredEndpointConfig == * lastEndpointConfigForUpdate ) {
77113 // 1. FailureReason alone does mean an update failed it can appear because of other reasons(patching/scaling failed)
78114 // 2. *desiredEndpointConfig == *lastEndpointConfigForUpdate only tells us an update was tried with lastEndpointConfigForUpdate
@@ -82,36 +118,19 @@ func (rm *resourceManager) customUpdateEndpoint(
82118 // 1 & 2 does not guarantee an update Failed. Hence we need to look at `*latestEndpointConfigName` to determine if the update was unsuccessful
83119 // `*desiredEndpointConfig != *latestEndpointConfig` + `*desiredEndpointConfig == *lastEndpointConfigForUpdate`+ `FailureReason != nil` indicate that an update is needed,
84120 // has already been tried and failed.
85- return nil , FailUpdateError
121+ return FailUpdateError
86122 }
87123
88- return nil , nil
89- }
90-
91- // customDeleteEndpoint adds specialized logic to requeueAfter until endpoint is in
92- // InService or Failed state before a deleteEndpoint can be called
93- func (rm * resourceManager ) customDeleteEndpoint (
94- ctx context.Context ,
95- latest * resource ,
96- ) error {
97- latestStatus := latest .ko .Status .EndpointStatus
98- if latestStatus != nil && * latestStatus == svcsdk .EndpointStatusFailed {
99- return nil
100- }
101- return rm .endpointStatusAllowUpdates (ctx , latest )
124+ return nil
102125}
103126
104- // endpointStatusAllowUpdates is a helper method to determine if endpoint allows modification
105- func (rm * resourceManager ) endpointStatusAllowUpdates (
127+ // requeueUntilCanModify creates and returns an ackrequeue error
128+ // if a resource's latest status matches any of the defined modifying statuses.
129+ // This is so the controller requeues until the resource can be modifed
130+ func (rm * resourceManager ) requeueUntilCanModify (
106131 ctx context.Context ,
107132 r * resource ,
108133) error {
109134 latestStatus := r .ko .Status .EndpointStatus
110- if latestStatus != nil && * latestStatus != svcsdk .EndpointStatusInService {
111- return requeue .NeededAfter (
112- errors .New ("endpoint status does not allow modification, it is not in 'InService' state" ),
113- requeue .DefaultRequeueAfterDuration )
114- }
115-
116- return nil
135+ return svccommon .RequeueIfModifying (latestStatus , & resourceName , & modifyingStatuses )
117136}
0 commit comments