github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/links/links.go (about) 1 package links 2 3 import ( 4 "fmt" 5 "net/url" 6 7 "github.com/pkg/errors" 8 "go.starlark.net/starlark" 9 "go.starlark.net/starlarkstruct" 10 11 "github.com/tilt-dev/tilt/pkg/model" 12 13 "github.com/tilt-dev/tilt/internal/tiltfile/starkit" 14 "github.com/tilt-dev/tilt/internal/tiltfile/value" 15 ) 16 17 type Link struct { 18 *starlarkstruct.Struct 19 model.Link 20 } 21 22 var _ starlark.Value = Link{} 23 24 // Parse resource links (string or `link`) into model.Link 25 // Not to be confused with a LinkED List :P 26 type LinkList struct { 27 Links []model.Link 28 } 29 30 func (ll *LinkList) Unpack(v starlark.Value) error { 31 seq := value.ValueOrSequenceToSlice(v) 32 for _, val := range seq { 33 switch val := val.(type) { 34 case starlark.String: 35 li, err := strToLink(val) 36 if err != nil { 37 return err 38 } 39 ll.Links = append(ll.Links, li) 40 case Link: 41 ll.Links = append(ll.Links, val.Link) 42 default: 43 return fmt.Errorf("`Want a string, a link, or a sequence of these; found %v (type: %T)", val, val) 44 } 45 } 46 return nil 47 } 48 49 func strToLink(s starlark.String) (model.Link, error) { 50 withScheme, err := parseAndMaybeAddScheme(string(s)) 51 if err != nil { 52 return model.Link{}, errors.Wrapf(err, "validating URL %q", string(s)) 53 } 54 return model.Link{URL: withScheme}, nil 55 } 56 57 func parseAndMaybeAddScheme(uStr string) (*url.URL, error) { 58 if uStr == "" { 59 return nil, fmt.Errorf("url empty") 60 } 61 u, err := url.Parse(uStr) 62 if err != nil { 63 // NOTE(maia): this unfortunately isn't a very robust check, `url.Parse` 64 // returns an error in very few cases, but it's better than nothing. 65 return nil, err 66 } 67 68 if u.Scheme == "" { 69 // If the given URL string doesn't have a scheme, assume it's http 70 u.Scheme = "http" 71 } 72 73 return u, nil 74 } 75 76 // Implements functions for dealing with k8s secret settings. 77 type Plugin struct{} 78 79 var _ starkit.Plugin = Plugin{} 80 81 func NewPlugin() Plugin { 82 return Plugin{} 83 } 84 85 func (e Plugin) OnStart(env *starkit.Environment) error { 86 return env.AddBuiltin("link", e.link) 87 } 88 89 func (e Plugin) link(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 90 var url, name string 91 92 if err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, 93 "url", &url, 94 "name?", &name); err != nil { 95 return nil, err 96 } 97 98 withScheme, err := parseAndMaybeAddScheme(url) 99 if err != nil { 100 return nil, errors.Wrapf(err, "validating URL %q", url) 101 } 102 103 return Link{ 104 Struct: starlarkstruct.FromStringDict(starlark.String("link"), starlark.StringDict{ 105 "url": starlark.String(withScheme.String()), 106 "name": starlark.String(name), 107 }), 108 Link: model.Link{ 109 URL: withScheme, 110 Name: name, 111 }, 112 }, nil 113 }