Skip to content

Commit 8b426c4

Browse files
authored
Merge pull request #565 from rushmash91/main
Switch ACK to CEL-Based Immutability and Remove Runtime Checks
2 parents 66c0f84 + 455e3d9 commit 8b426c4

File tree

7 files changed

+26
-58
lines changed

7 files changed

+26
-58
lines changed

pkg/config/field.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,9 @@ type FieldConfig struct {
408408
// IsSecret instructs the code generator that this field should be a
409409
// SecretKeyReference.
410410
IsSecret bool `json:"is_secret"`
411-
// IsImmutable instructs the code generator to add advisory conditions
412-
// if user modifies the spec field after resource was created.
411+
// IsImmutable indicates that the field is enforced as immutable at the
412+
// admission layer. The code generator will add kubebuilder:validation:XValidation
413+
// lines to the CRD, preventing changes to this field after it’s set.
413414
IsImmutable bool `json:"is_immutable"`
414415
// From instructs the code generator that the value of the field should
415416
// be retrieved from the specified operation and member path

pkg/model/crd.go

-27
Original file line numberDiff line numberDiff line change
@@ -336,33 +336,6 @@ func (r *CRD) IsSecretField(path string) bool {
336336
return false
337337
}
338338

339-
// GetImmutableFieldPaths returns list of immutable field paths present in CRD
340-
func (r *CRD) GetImmutableFieldPaths() []string {
341-
fConfigs := r.cfg.GetFieldConfigs(r.Names.Original)
342-
var immutableFields []string
343-
344-
for field, fieldConfig := range fConfigs {
345-
if fieldConfig.IsImmutable {
346-
immutableFields = append(immutableFields, field)
347-
}
348-
}
349-
350-
// We need a deterministic order to traverse the immutable fields
351-
sort.Strings(immutableFields)
352-
return immutableFields
353-
}
354-
355-
// HasImmutableFieldChanges helper function that return true if there are any immutable field changes
356-
func (r *CRD) HasImmutableFieldChanges() bool {
357-
fConfigs := r.cfg.GetFieldConfigs(r.Names.Original)
358-
for _, fieldConfig := range fConfigs {
359-
if fieldConfig.IsImmutable {
360-
return true
361-
}
362-
}
363-
return false
364-
}
365-
366339
// OmitUnchangedFieldsOnUpdate returns whether the controller needs to omit
367340
// unchanged fields from an update request or not.
368341
func (r *CRD) OmitUnchangedFieldsOnUpdate() bool {

pkg/model/field.go

+12
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ func (f *Field) IsRequired() bool {
188188
)
189189
}
190190

191+
// IsImmutable checks the FieldConfig for the Field and returns true if the
192+
// field is marked as immutable.
193+
//
194+
// If the FieldConfig is nil or IsImmutable is false (or not set), this function
195+
// returns false.
196+
func (f *Field) IsImmutable() bool {
197+
if f.FieldConfig != nil && f.FieldConfig.IsImmutable {
198+
return true
199+
}
200+
return false
201+
}
202+
191203
// GetSetterConfig returns the SetFieldConfig object associated with this field
192204
// and a supplied operation type, or nil if none exists.
193205
func (f *Field) GetSetterConfig(opType OpType) *ackgenconfig.SetFieldConfig {

templates/apis/crd.go.tpl

+10-4
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@ type {{ .CRD.Kind }}Spec struct {
1919
{{ if $field.GetDocumentation -}}
2020
{{ $field.GetDocumentation }}
2121
{{ end -}}
22-
{{- if and ($field.IsRequired) (not $field.HasReference) -}}
22+
23+
{{- if $field.IsImmutable }}
24+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable once set"
25+
{{- end }}
26+
27+
{{- if and ($field.IsRequired) (not $field.HasReference) }}
2328
// +kubebuilder:validation:Required
24-
{{ end -}}
29+
{{- end }}
30+
2531
{{ $field.Names.Camel }} {{ $field.GoType }} {{ $field.GetGoTag }}
2632
{{- end }}
2733
}
@@ -33,7 +39,7 @@ type {{ .CRD.Kind }}Status struct {
3339
// constructed ARN for the resource
3440
// +kubebuilder:validation:Optional
3541
ACKResourceMetadata *ackv1alpha1.ResourceMetadata `json:"ackResourceMetadata"`
36-
// All CRS managed by ACK have a common `Status.Conditions` member that
42+
// All CRs managed by ACK have a common `Status.Conditions` member that
3743
// contains a collection of `ackv1alpha1.Condition` objects that describe
3844
// the various terminal states of the CR and its backend AWS service API
3945
// resource
@@ -80,4 +86,4 @@ type {{ .CRD.Kind }}List struct {
8086

8187
func init() {
8288
SchemeBuilder.Register(&{{ .CRD.Kind }}{}, &{{ .CRD.Kind }}List{})
83-
}
89+
}

templates/crossplane/apis/crd.go.tpl

+1-2
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,4 @@ var (
9393

9494
func init() {
9595
SchemeBuilder.Register(&{{ .CRD.Kind }}{}, &{{ .CRD.Kind }}List{})
96-
}
97-
96+
}

templates/pkg/resource/sdk.go.tpl

-17
Original file line numberDiff line numberDiff line change
@@ -332,23 +332,6 @@ func (rm *resourceManager) terminalAWSError(err error) bool {
332332
{{- end }}
333333
}
334334

335-
{{- if .CRD.HasImmutableFieldChanges }}
336-
// getImmutableFieldChanges returns list of immutable fields from the
337-
func (rm *resourceManager) getImmutableFieldChanges(
338-
delta *ackcompare.Delta,
339-
) []string {
340-
var fields []string;
341-
{{- $prefixConfig := .CRD.Config.PrefixConfig }}
342-
{{- range $immutableField := .CRD.GetImmutableFieldPaths }}
343-
{{- $specPrefix := $prefixConfig.SpecField }}
344-
if delta.DifferentAt("{{ TrimPrefix $specPrefix "." }}.{{$immutableField}}") {
345-
fields = append(fields,"{{$immutableField}}")
346-
}
347-
{{- end }}
348-
349-
return fields
350-
}
351-
{{- end }}
352335
{{- if $hookCode := Hook .CRD "sdk_file_end" }}
353336
{{ $hookCode }}
354337
{{- end }}

templates/pkg/resource/sdk_update.go.tpl

-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ func (rm *resourceManager) sdkUpdate(
1010
defer func() {
1111
exit(err)
1212
}()
13-
{{- if .CRD.HasImmutableFieldChanges }}
14-
if immutableFieldChanges := rm.getImmutableFieldChanges(delta); len(immutableFieldChanges) > 0 {
15-
msg := fmt.Sprintf("Immutable Spec fields have been modified: %s", strings.Join(immutableFieldChanges, ","))
16-
return nil, ackerr.NewTerminalError(fmt.Errorf(msg))
17-
}
18-
{{- end }}
1913
{{- if $hookCode := Hook .CRD "sdk_update_pre_build_request" }}
2014
{{ $hookCode }}
2115
{{- end }}

0 commit comments

Comments
 (0)