github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/k8s/locators.go (about)

     1  package k8s
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"go.starlark.net/starlark"
     7  
     8  	"github.com/pkg/errors"
     9  
    10  	"github.com/tilt-dev/tilt/internal/k8s"
    11  	"github.com/tilt-dev/tilt/internal/tiltfile/value"
    12  )
    13  
    14  // Deserializing locators from starlark values.
    15  type JSONPathImageLocatorListSpec struct {
    16  	Specs []JSONPathImageLocatorSpec
    17  }
    18  
    19  func (s JSONPathImageLocatorListSpec) IsEmpty() bool {
    20  	return len(s.Specs) == 0
    21  }
    22  
    23  func (s *JSONPathImageLocatorListSpec) Unpack(v starlark.Value) error {
    24  	list := value.ValueOrSequenceToSlice(v)
    25  	for _, item := range list {
    26  		spec := JSONPathImageLocatorSpec{}
    27  		err := spec.Unpack(item)
    28  		if err != nil {
    29  			return err
    30  		}
    31  		s.Specs = append(s.Specs, spec)
    32  	}
    33  	return nil
    34  }
    35  
    36  func (s JSONPathImageLocatorListSpec) ToImageLocators(selector k8s.ObjectSelector) ([]k8s.ImageLocator, error) {
    37  	result := []k8s.ImageLocator{}
    38  	for _, spec := range s.Specs {
    39  		locator, err := spec.ToImageLocator(selector)
    40  		if err != nil {
    41  			return nil, err
    42  		}
    43  		result = append(result, locator)
    44  	}
    45  	return result, nil
    46  }
    47  
    48  type JSONPathImageLocatorSpec struct {
    49  	jsonPath string
    50  }
    51  
    52  func (s *JSONPathImageLocatorSpec) Unpack(v starlark.Value) error {
    53  	var ok bool
    54  	s.jsonPath, ok = starlark.AsString(v)
    55  	if !ok {
    56  		return fmt.Errorf("Expected string, got: %s", v)
    57  	}
    58  	return nil
    59  }
    60  
    61  func (s JSONPathImageLocatorSpec) ToImageLocator(selector k8s.ObjectSelector) (k8s.ImageLocator, error) {
    62  	return k8s.NewJSONPathImageLocator(selector, s.jsonPath)
    63  }
    64  
    65  type JSONPathImageObjectLocatorSpec struct {
    66  	jsonPath  string
    67  	repoField string
    68  	tagField  string
    69  }
    70  
    71  func (s JSONPathImageObjectLocatorSpec) IsEmpty() bool {
    72  	return s == JSONPathImageObjectLocatorSpec{}
    73  }
    74  
    75  func (s *JSONPathImageObjectLocatorSpec) Unpack(v starlark.Value) error {
    76  	d, ok := v.(*starlark.Dict)
    77  	if !ok {
    78  		return fmt.Errorf("Expected dict of the form {'json_path': str, 'repo_field': str, 'tag_field': str}. Actual: %s", v)
    79  	}
    80  
    81  	values, err := validateStringDict(d, []string{"json_path", "repo_field", "tag_field"})
    82  	if err != nil {
    83  		return errors.Wrap(err, "Expected dict of the form {'json_path': str, 'repo_field': str, 'tag_field': str}")
    84  	}
    85  
    86  	s.jsonPath, s.repoField, s.tagField = values[0], values[1], values[2]
    87  	return nil
    88  }
    89  
    90  func (s JSONPathImageObjectLocatorSpec) ToImageLocator(selector k8s.ObjectSelector) (k8s.ImageLocator, error) {
    91  	return k8s.NewJSONPathImageObjectLocator(selector, s.jsonPath, s.repoField, s.tagField)
    92  }
    93  
    94  func validateStringDict(d *starlark.Dict, expectedFields []string) ([]string, error) {
    95  	indices := map[string]int{}
    96  	result := make([]string, len(expectedFields))
    97  	for i, f := range expectedFields {
    98  		indices[f] = i
    99  	}
   100  
   101  	for _, item := range d.Items() {
   102  		key, val := item[0], item[1]
   103  		keyString, ok := starlark.AsString(key)
   104  		if !ok {
   105  			return nil, fmt.Errorf("Unexpected key: %s", key)
   106  		}
   107  
   108  		index, ok := indices[keyString]
   109  		if !ok {
   110  			return nil, fmt.Errorf("Unexpected key: %s", key)
   111  		}
   112  
   113  		valString, ok := starlark.AsString(val)
   114  		if !ok {
   115  			return nil, fmt.Errorf("Expected string at key %q. Got: %s", key, val.Type())
   116  		}
   117  
   118  		result[index] = valString
   119  	}
   120  
   121  	if len(d.Items()) != len(expectedFields) {
   122  		return nil, fmt.Errorf("Missing keys. Actual keys: %s", d.Keys())
   123  	}
   124  	return result, nil
   125  }