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

     1  package v1alpha1
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"go.starlark.net/starlark"
     8  	"k8s.io/apimachinery/pkg/util/validation/field"
     9  
    10  	"github.com/tilt-dev/tilt/internal/controllers/apicmp"
    11  	"github.com/tilt-dev/tilt/internal/controllers/apiset"
    12  	"github.com/tilt-dev/tilt/internal/tiltfile/starkit"
    13  	"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
    14  )
    15  
    16  // Defines starlark functions that register API objects
    17  // from the v1alpha1 API.
    18  //
    19  // Eventually, all the files in this module should be autogenerated from
    20  // the data models.
    21  type Plugin struct {
    22  }
    23  
    24  func NewPlugin() Plugin {
    25  	return Plugin{}
    26  }
    27  
    28  func (e Plugin) NewState() interface{} {
    29  	return apiset.ObjectSet{}
    30  }
    31  
    32  func (p Plugin) OnStart(env *starkit.Environment) error {
    33  	return p.registerSymbols(env)
    34  }
    35  
    36  // Register an API object, so that it's reconciled against the API server when
    37  // tiltfile execution completes.
    38  func (p Plugin) register(t *starlark.Thread, obj apiset.Object) (starlark.Value, error) {
    39  	objV, ok := obj.(validator)
    40  	if ok {
    41  		err := objV.Validate(context.TODO())
    42  		if err != nil {
    43  			return nil, err.ToAggregate()
    44  		}
    45  	}
    46  
    47  	err := starkit.SetState(t, func(set apiset.ObjectSet) (apiset.ObjectSet, error) {
    48  		typedSet := set.GetOrCreateTypedSet(obj)
    49  		name := obj.GetName()
    50  		existing, exists := typedSet[name]
    51  		if exists {
    52  			// tiltextension adds this for extensions, but new objects will not
    53  			// have this annotation yet, so delete for comparison
    54  			delete(existing.GetAnnotations(), v1alpha1.AnnotationManagedBy)
    55  			if !apicmp.DeepEqual(obj, existing) {
    56  				return set, fmt.Errorf("%s %q already registered", obj.GetGroupVersionResource().Resource, name)
    57  			}
    58  		}
    59  
    60  		typedSet[name] = obj
    61  		return set, nil
    62  	})
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	return starlark.None, nil
    67  }
    68  
    69  var _ starkit.StatefulPlugin = Plugin{}
    70  
    71  func MustState(model starkit.Model) apiset.ObjectSet {
    72  	state, err := GetState(model)
    73  	if err != nil {
    74  		panic(err)
    75  	}
    76  	return state
    77  }
    78  
    79  func GetState(m starkit.Model) (apiset.ObjectSet, error) {
    80  	var state apiset.ObjectSet
    81  	err := m.Load(&state)
    82  	return state, err
    83  }
    84  
    85  type validator interface {
    86  	Validate(ctx context.Context) field.ErrorList
    87  }