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 }