...

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

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

     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 dcl
    16  
    17  import (
    18  	"fmt"
    19  
    20  	dclextension "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/extension"
    21  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
    22  
    23  	"github.com/nasa9084/go-openapi"
    24  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    25  )
    26  
    27  // Resource is a wrapper around k8s.Resource and adds information regarding its
    28  // corresponding DCL resource and maintains an original copy of the
    29  // k8s.Resource.
    30  type Resource struct {
    31  	k8s.Resource `json:",inline"`
    32  
    33  	Original *k8s.Resource `json:"-"`
    34  
    35  	// Fields related to DCL processing
    36  	Schema *openapi.Schema `json:"-"`
    37  }
    38  
    39  func NewResource(u *unstructured.Unstructured, schema *openapi.Schema) (*Resource, error) {
    40  	resource := &Resource{
    41  		Schema: schema,
    42  	}
    43  
    44  	r, err := k8s.NewResource(u)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	resource.Resource = *r
    49  
    50  	// Intentionally re-create the K8s resource to create a separate copy.
    51  	resource.Original, err = k8s.NewResource(u)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	if err := resource.ValidateResourceIDIfSupported(); err != nil {
    57  		return nil, err
    58  	}
    59  	return resource, nil
    60  }
    61  
    62  func (r *Resource) ValidateResourceIDIfSupported() error {
    63  	// The resource ID is represented by the top level 'name' field consistently in DCL.
    64  	_, found := dclextension.GetNameFieldSchema(r.Schema)
    65  	if !found {
    66  		// The resource doesn't have a 'resourceID' field.
    67  		return nil
    68  	}
    69  
    70  	_, err := r.IsResourceIDConfigured()
    71  	if err != nil {
    72  		return fmt.Errorf("error validating '%s' field: %w", k8s.ResourceIDFieldPath, err)
    73  	}
    74  	return nil
    75  }
    76  
    77  func (r *Resource) HasServerGeneratedIDButNotConfigured() (bool, error) {
    78  	s, found := dclextension.GetNameFieldSchema(r.Schema)
    79  	if !found {
    80  		// The resource doesn't have a 'resourceID' field.
    81  		return false, nil
    82  	}
    83  
    84  	isServerGenerated, isConfigured, err := r.getResourceIDMetadata(s)
    85  	if err != nil {
    86  		return false, err
    87  	}
    88  	return isServerGenerated && !isConfigured, nil
    89  }
    90  
    91  func (r *Resource) HasServerGeneratedIDAndConfigured() (bool, error) {
    92  	s, found := dclextension.GetNameFieldSchema(r.Schema)
    93  	if !found {
    94  		// The resource doesn't have a 'resourceID' field.
    95  		return false, nil
    96  	}
    97  	isServerGenerated, isConfigured, err := r.getResourceIDMetadata(s)
    98  	if err != nil {
    99  		return false, err
   100  	}
   101  	return isServerGenerated && isConfigured, nil
   102  }
   103  
   104  func (r *Resource) getResourceIDMetadata(s *openapi.Schema) (isServerGenerated bool, isConfigured bool, err error) {
   105  	isConfigured, err = r.IsResourceIDConfigured()
   106  	if err != nil {
   107  		return false, false, fmt.Errorf("error checking if '%s' field is configured: %w", k8s.ResourceIDFieldPath, err)
   108  	}
   109  	isServerGenerated, err = dclextension.IsResourceIDFieldServerGenerated(s)
   110  	if err != nil {
   111  		return false, false, fmt.Errorf("error parsing `resourceID` field schema: %w", err)
   112  	}
   113  	return isServerGenerated, isConfigured, nil
   114  }
   115  
   116  func (r *Resource) HasMutableButUnreadableFields() (bool, error) {
   117  	// The resource uses the state-hint directive if it contains any mutable but
   118  	// unreadable fields. The state-hint directive is only used by mutable but
   119  	// unreadable fields.
   120  	hasStateHint, err := dclextension.HasStateHint(r.Schema)
   121  	if err != nil {
   122  		return false, err
   123  	}
   124  	return hasStateHint, nil
   125  }
   126  

View as plain text