...

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

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

     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 resourceoverrides
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
    21  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/resourceoverrides/operations"
    22  
    23  	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
    24  	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    25  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    26  	"k8s.io/apimachinery/pkg/runtime/schema"
    27  )
    28  
    29  // CRDDecorate decorates the given CRD to ensure that its schemas are authored correctly.
    30  // It could be used to preserve legacy fields, to mark fields optional with defaults, etc.
    31  type CRDDecorate func(crd *apiextensions.CustomResourceDefinition) error
    32  
    33  // PreActuationTransform transforms the original spec to the golden format that the resource actuator can understand.
    34  // For example, it could be used to fetch value from the legacy field and place it to the field that the resource actuator actually understands and supports.
    35  type PreActuationTransform func(r *k8s.Resource) error
    36  
    37  // PostActuationTransform transform the reconciled resource object.
    38  // A typical example of post-actuation transformations is to preserve the user specified fields.
    39  type PostActuationTransform func(original, reconciled *k8s.Resource, tfState *terraform.InstanceState, dclState *unstructured.Unstructured) error
    40  
    41  // ConfigValidate validates the input configuration in the webhook.
    42  type ConfigValidate func(r *unstructured.Unstructured) error
    43  
    44  // PreTerraformExport transforms the exported terraform prior to writing it.
    45  // A typical example of a transformation is to map our internal terraform types to real types.
    46  type PreTerraformExport func(ctx context.Context, op *operations.TerraformExport) error
    47  
    48  // PostUpdateStatusTransform transforms the resource object after its status is being updated.
    49  type PostUpdateStatusTransform func(r *k8s.Resource) error
    50  
    51  // ResourceOverride holds all pieces of changes needed, i.e. decoration, transformation and validation to author
    52  // a resource-specific behavior override.
    53  // Since one particular resource kind could have multiple overrides, each ResourceOverride should be logically orthogonal to each other and neutral to order of execution.
    54  type ResourceOverride struct {
    55  	CRDDecorate               CRDDecorate
    56  	ConfigValidate            ConfigValidate
    57  	PreActuationTransform     PreActuationTransform
    58  	PostActuationTransform    PostActuationTransform
    59  	PreTerraformExport        PreTerraformExport
    60  	PostUpdateStatusTransform PostUpdateStatusTransform
    61  }
    62  
    63  type ResourceOverrides struct {
    64  	Kind      string
    65  	Overrides []ResourceOverride
    66  }
    67  
    68  type ResourceOverridesHandler struct {
    69  	overridesPerKindMap map[string]ResourceOverrides
    70  }
    71  
    72  func NewResourceOverridesHandler() *ResourceOverridesHandler {
    73  	return &ResourceOverridesHandler{
    74  		overridesPerKindMap: make(map[string]ResourceOverrides),
    75  	}
    76  }
    77  
    78  var Handler = NewResourceOverridesHandler()
    79  
    80  func (h *ResourceOverridesHandler) CRDDecorate(crd *apiextensions.CustomResourceDefinition) error {
    81  	kind := crd.Spec.Names.Kind
    82  	ro, found := h.registration(kind)
    83  	if !found {
    84  		return nil
    85  	}
    86  	for _, o := range ro.Overrides {
    87  		if o.CRDDecorate != nil {
    88  			if err := o.CRDDecorate(crd); err != nil {
    89  				return err
    90  			}
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  func (h *ResourceOverridesHandler) ConfigValidate(r *unstructured.Unstructured) error {
    97  	kind := r.GetKind()
    98  	ro, found := h.registration(kind)
    99  	if !found {
   100  		return nil
   101  	}
   102  	for _, o := range ro.Overrides {
   103  		if o.ConfigValidate != nil {
   104  			if err := o.ConfigValidate(r); err != nil {
   105  				return err
   106  			}
   107  		}
   108  	}
   109  	return nil
   110  }
   111  
   112  func (h *ResourceOverridesHandler) PreActuationTransform(r *k8s.Resource) error {
   113  	ro, found := h.registration(r.Kind)
   114  	if !found {
   115  		return nil
   116  	}
   117  	for _, o := range ro.Overrides {
   118  		if o.PreActuationTransform != nil {
   119  			if err := o.PreActuationTransform(r); err != nil {
   120  				return err
   121  			}
   122  		}
   123  	}
   124  	return nil
   125  }
   126  
   127  func (h *ResourceOverridesHandler) PostActuationTransform(original, post *k8s.Resource, tfState *terraform.InstanceState, dclState *unstructured.Unstructured) error {
   128  	ro, found := h.registration(original.Kind)
   129  	if !found {
   130  		return nil
   131  	}
   132  	for _, o := range ro.Overrides {
   133  		if o.PostActuationTransform != nil {
   134  			if err := o.PostActuationTransform(original, post, tfState, dclState); err != nil {
   135  				return err
   136  			}
   137  		}
   138  	}
   139  	return nil
   140  }
   141  
   142  func (h *ResourceOverridesHandler) PreTerraformExport(ctx context.Context, gvk schema.GroupVersionKind, op *operations.TerraformExport) error {
   143  	kind := gvk.Kind
   144  	ro, found := h.registration(kind)
   145  	if !found {
   146  		return nil
   147  	}
   148  	for _, o := range ro.Overrides {
   149  		if o.PreTerraformExport != nil {
   150  			if err := o.PreTerraformExport(ctx, op); err != nil {
   151  				return err
   152  			}
   153  		}
   154  	}
   155  	return nil
   156  }
   157  
   158  func (h *ResourceOverridesHandler) PostUpdateStatusTransform(r *k8s.Resource) error {
   159  	ro, found := h.registration(r.Kind)
   160  	if !found {
   161  		return nil
   162  	}
   163  	for _, o := range ro.Overrides {
   164  		if o.PostUpdateStatusTransform != nil {
   165  			if err := o.PostUpdateStatusTransform(r); err != nil {
   166  				return err
   167  			}
   168  		}
   169  	}
   170  	return nil
   171  }
   172  
   173  func (h *ResourceOverridesHandler) HasOverrides(kind string) bool {
   174  	_, found := h.registration(kind)
   175  	return found
   176  }
   177  
   178  func (h *ResourceOverridesHandler) HasConfigValidate(kind string) bool {
   179  	ro, found := h.registration(kind)
   180  	if !found {
   181  		return false
   182  	}
   183  	for _, o := range ro.Overrides {
   184  		if o.ConfigValidate != nil {
   185  			return true
   186  		}
   187  	}
   188  	return false
   189  }
   190  
   191  func (h *ResourceOverridesHandler) registration(kind string) (*ResourceOverrides, bool) {
   192  	ro, found := h.overridesPerKindMap[kind]
   193  	if !found {
   194  		return nil, false
   195  	}
   196  	return &ro, found
   197  }
   198  
   199  func (h *ResourceOverridesHandler) Register(ro ResourceOverrides) {
   200  	h.overridesPerKindMap[ro.Kind] = ro
   201  }
   202  
   203  func init() {
   204  	Handler.Register(GetStorageBucketResourceOverrides())
   205  	Handler.Register(GetSQLInstanceResourceOverrides())
   206  	Handler.Register(GetContainerClusterResourceOverrides())
   207  	Handler.Register(GetLoggingLogSinkResourceOverrides())
   208  	Handler.Register(GetComputeInstanceResourceOverrides())
   209  	Handler.Register(GetDNSRecordSetOverrides())
   210  	Handler.Register(GetComputeBackendServiceResourceOverrides())
   211  	Handler.Register(GetVPCAccessConnectorResourceOverrides())
   212  
   213  	// IAM
   214  	Handler.Register(GetIAMCustomRoleResourceOverrides())
   215  }
   216  

View as plain text