Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/generate/config/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ type FieldConfig struct {
// IsSecret instructs the code generator that this field should be a
// SecretKeyReference.
IsSecret bool `json:"is_secret"`
// IsImmutable instructs the code generator to add advisory conditions
// if user modifies the spec field after resource was created.
IsImmutable bool `json:"is_immutable"`
// From instructs the code generator that the value of the field should
// be retrieved from the specified operation and member path
From *SourceFieldConfig `json:"from,omitempty"`
Expand Down
26 changes: 26 additions & 0 deletions pkg/model/crd.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,32 @@ func (r *CRD) IsSecretField(path string) bool {
return false
}

// GetImmutableFieldPaths returns list of immutable field paths present in CRD
func (r *CRD) GetImmutableFieldPaths() []string {
fConfigs := r.cfg.ResourceFields(r.Names.Original)
var immutableFields []string

for field, fieldConfig := range fConfigs {
if fieldConfig.IsImmutable {
immutableFields = append(immutableFields, field)
}
}

return immutableFields
}

// HasImmutableFieldChanges helper function that return true if there are any immutable field changes
func (r *CRD) HasImmutableFieldChanges() bool {
fConfigs := r.cfg.ResourceFields(r.Names.Original)

for _, fieldConfig := range fConfigs {
if fieldConfig.IsImmutable {
return true
}
}
return false
}

// SetOutputCustomMethodName returns custom set output operation as *string for
// given operation on custom resource, if specified in generator config
func (r *CRD) SetOutputCustomMethodName(
Expand Down
60 changes: 60 additions & 0 deletions templates/pkg/resource/sdk.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,63 @@ func (rm *resourceManager) terminalAWSError(err error) bool {
return false
{{- end }}
}

{{- if .CRD.HasImmutableFieldChanges }}
// getImmutableFieldChanges returns list of immutable fields from the
func (rm *resourceManager) getImmutableFieldChanges(
delta *ackcompare.Delta,
) []string {
var fields []string;

{{- range $immutableField := .CRD.GetImmutableFieldPaths }}
if delta.DifferentAt("{{$immutableField}}") {
fields = append(fields,"{{$immutableField}}")
}
{{- end }}

return fields
}

// handleImmutableFieldsChangedCondition validates the immutable fields and set appropriate condition
func (rm *resourceManager) handleImmutableFieldsChangedCondition(
r *resource,
delta *ackcompare.Delta,
) *resource {

fields := rm.getImmutableFieldChanges(delta)
ko := r.ko.DeepCopy()
var advisoryCondition *ackv1alpha1.Condition = nil
for _, condition := range ko.Status.Conditions {
if condition.Type == ackv1alpha1.ConditionTypeAdvisory {
advisoryCondition = condition
break
}
}

// Remove the advisory condition if issue is no longer present
if len(fields) == 0 && advisoryCondition != nil{
var newConditions []*ackv1alpha1.Condition
for _, condition := range ko.Status.Conditions {
if condition.Type != ackv1alpha1.ConditionTypeAdvisory {
newConditions = append(newConditions,condition)
}
}
ko.Status.Conditions = newConditions
}

if len(fields) > 0 {
if advisoryCondition == nil {
advisoryCondition = &ackv1alpha1.Condition{
Type: ackv1alpha1.ConditionTypeAdvisory,
}
ko.Status.Conditions = append(ko.Status.Conditions, advisoryCondition)
}

advisoryCondition.Status = corev1.ConditionTrue
message := "Immutable Spec fields have been modified : " + strings.Join(fields, ",")
advisoryCondition.Message = &message
}

return &resource{ko}
}
{{- end }}
3 changes: 3 additions & 0 deletions templates/pkg/resource/sdk_update.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ func (rm *resourceManager) sdkUpdate(
if respErr != nil {
return nil, respErr
}
{{- if .CRD.HasImmutableFieldChanges }}
desired = rm.handleImmutableFieldsChangedCondition(desired, delta)
{{- end }}
// Merge in the information we read from the API call above to the copy of
// the original Kubernetes object we passed to the function
ko := desired.ko.DeepCopy()
Expand Down