...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s/status.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package k8s
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/crd/crdgeneration/crdboilerplate"
    21  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/text"
    22  
    23  	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    24  )
    25  
    26  var renameStatusFieldsWithReservedNamesExcludeList = map[string]bool{
    27  	// This resource was already released with no 'resource' prefix prepended to `.status.conditions` field in CRD.
    28  	// Added to the list to avoid breaking change.
    29  	"google_storage_default_object_access_control": true,
    30  }
    31  
    32  func RenameStatusFieldsWithReservedNames(status *apiextensions.JSONSchemaProps) (*apiextensions.JSONSchemaProps, error) {
    33  	statusCopy := status.DeepCopy()
    34  	for field := range ReservedStatusFieldNames() {
    35  		renamedField := RenameStatusFieldWithReservedName(field)
    36  
    37  		// Error out if status has fields that collide with the renames
    38  		// themselves (e.g. "resourceConditions"). We error out here even if
    39  		// there are no fields that need to be renamed in order to defend
    40  		// against the case where the resource does introduce a name collision
    41  		// later (e.g. suppose status has "resourceConditions", but not
    42  		// "conditions", but then adds "conditions" later).
    43  		// TODO(b/213888818): Handle fields that collide with the renames.
    44  		if _, ok := statusCopy.Properties[renamedField]; ok {
    45  			return nil, fmt.Errorf("status schema already has a field named "+
    46  				"'%v' which is the rename meant for fields that collide "+
    47  				"with the reserved name '%v'", renamedField, field)
    48  		}
    49  
    50  		// Rename fields that collide with reserved names
    51  		if schema, ok := statusCopy.Properties[field]; ok {
    52  			statusCopy.Properties[renamedField] = schema
    53  			delete(statusCopy.Properties, field)
    54  		}
    55  	}
    56  
    57  	return statusCopy, nil
    58  }
    59  
    60  func RenameStatusFieldsWithReservedNamesIfResourceNotExcluded(tfResourceName string, status *apiextensions.JSONSchemaProps) (*apiextensions.JSONSchemaProps, error) {
    61  	if shouldSkip(tfResourceName) {
    62  		return status, nil
    63  	}
    64  	return RenameStatusFieldsWithReservedNames(status)
    65  }
    66  
    67  func ReservedStatusFieldNames() map[string]bool {
    68  	reservedFieldNames := make(map[string]bool)
    69  
    70  	// Status field names that are in use
    71  	crdSchema := crdboilerplate.GetOpenAPIV3SchemaSkeleton()
    72  	for fieldName := range crdSchema.Properties["status"].Properties {
    73  		reservedFieldNames[fieldName] = true
    74  	}
    75  
    76  	// Status field names that might be used in the future
    77  	for _, fieldName := range ReservedStatusFieldNamesForFutureUse {
    78  		reservedFieldNames[fieldName] = true
    79  	}
    80  	return reservedFieldNames
    81  }
    82  
    83  func RenameStatusFieldWithReservedName(field string) string {
    84  	return "resource" + text.UppercaseInitial(field)
    85  }
    86  
    87  func RenameStatusFieldWithReservedNameIfResourceNotExcluded(tfResourceName, field string) string {
    88  	if shouldSkip(tfResourceName) {
    89  		return field
    90  	}
    91  	return RenameStatusFieldWithReservedName(field)
    92  }
    93  
    94  // shouldSkip returns true if the tfResourceName is included in renameStatusFieldsWithReservedNamesExcludeList.
    95  func shouldSkip(tfResourceName string) bool {
    96  	if _, found := renameStatusFieldsWithReservedNamesExcludeList[tfResourceName]; found {
    97  		return true
    98  	}
    99  	return false
   100  }
   101  

View as plain text