11
11
// express or implied. See the License for the specific language governing
12
12
// permissions and limitations under the License.
13
13
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
16
16
17
17
package endpoint
18
18
19
19
import (
20
20
"context"
21
- "errors"
22
21
"strings"
23
22
24
23
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"
26
27
"github.com/aws/aws-sdk-go/aws/awserr"
27
28
svcsdk "github.com/aws/aws-sdk-go/service/sagemaker"
28
29
)
29
30
30
31
var (
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
+
31
42
FailUpdateError = awserr .New ("EndpointUpdateError" , "unable to update endpoint. check FailureReason" , nil )
32
43
33
44
FailureReasonInternalServiceErrorPrefix = "Request to service failed"
34
45
)
35
46
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
37
82
// proceeed with updateEndpoint call.
38
83
// Update is blocked in the following cases:
39
- // 1. while EndpointStatus != InService
84
+ // 1. while EndpointStatus != InService (handled by requeueUntilCanModify method)
40
85
// 2. EndpointStatus == Failed
41
86
// 3. A previous update to the Endpoint with same endpointConfigName failed
42
87
// Method returns nil if endpoint can be updated, otherwise error depending on above cases
43
- func (rm * resourceManager ) customUpdateEndpoint (
88
+ func (rm * resourceManager ) customUpdateEndpointPreChecks (
44
89
ctx context.Context ,
45
90
desired * resource ,
46
91
latest * resource ,
47
92
delta * ackcompare.Delta ,
48
- ) ( * resource , error ) {
93
+ ) error {
49
94
latestStatus := latest .ko .Status .EndpointStatus
50
95
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
60
97
}
61
98
62
99
failureReason := latest .ko .Status .FailureReason
63
- latestEndpointConfig := latest .ko .Spec .EndpointConfigName
64
100
desiredEndpointConfig := desired .ko .Spec .EndpointConfigName
65
101
lastEndpointConfigForUpdate := desired .ko .Status .LastEndpointConfigNameForUpdate
66
102
@@ -72,7 +108,7 @@ func (rm *resourceManager) customUpdateEndpoint(
72
108
// "Request to service failed" means update failed because of ISE and can be retried
73
109
(failureReason != nil && lastEndpointConfigForUpdate != nil &&
74
110
! strings .HasPrefix (* failureReason , FailureReasonInternalServiceErrorPrefix ) &&
75
- * desiredEndpointConfig != * latestEndpointConfig &&
111
+ delta . DifferentAt ( "Spec.EndpointConfigName" ) &&
76
112
* desiredEndpointConfig == * lastEndpointConfigForUpdate ) {
77
113
// 1. FailureReason alone does mean an update failed it can appear because of other reasons(patching/scaling failed)
78
114
// 2. *desiredEndpointConfig == *lastEndpointConfigForUpdate only tells us an update was tried with lastEndpointConfigForUpdate
@@ -82,36 +118,19 @@ func (rm *resourceManager) customUpdateEndpoint(
82
118
// 1 & 2 does not guarantee an update Failed. Hence we need to look at `*latestEndpointConfigName` to determine if the update was unsuccessful
83
119
// `*desiredEndpointConfig != *latestEndpointConfig` + `*desiredEndpointConfig == *lastEndpointConfigForUpdate`+ `FailureReason != nil` indicate that an update is needed,
84
120
// has already been tried and failed.
85
- return nil , FailUpdateError
121
+ return FailUpdateError
86
122
}
87
123
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
102
125
}
103
126
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 (
106
131
ctx context.Context ,
107
132
r * resource ,
108
133
) error {
109
134
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 )
117
136
}
0 commit comments