diff --git a/go.mod b/go.mod index 2e89ab65f..243fa4a05 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ module carvel.dev/kapp -go 1.23.3 +go 1.23.2 require ( + carvel.dev/ytt v0.51.0 github.com/cppforlife/cobrautil v0.0.0-20221130162803-acdfead391ef github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835 github.com/cppforlife/go-cli-ui v0.0.0-20220425131040-94f26b16bc14 @@ -10,7 +11,6 @@ require ( github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-version v1.6.0 github.com/k14s/difflib v0.0.0-20240118055029-596a7a5585c3 - github.com/k14s/ytt v0.36.0 github.com/mitchellh/go-wordwrap v1.0.1 github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index eae5d34e1..39084b09b 100644 --- a/go.sum +++ b/go.sum @@ -1,59 +1,26 @@ carvel.dev/vendir v0.40.0 h1:JdhCp/EjAPGI8F5zoAVYwZHf1sPEFee19RpgGb3ciT8= carvel.dev/vendir v0.40.0/go.mod h1:XPdluJu7322RZNx05AA4gYnV52aKywBdh7Ma12GuM2Q= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-lambda-go v1.26.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +carvel.dev/ytt v0.51.0 h1:mkH/7+WBqYEEv4MAU5CRmjte82NvSwMiMhF4sHfATlA= +carvel.dev/ytt v0.51.0/go.mod h1:1mkMIMghLgdMp8Lqa0pj92aDyVo3vOd33XplyAxYHM0= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cppforlife/cobrautil v0.0.0-20200514214827-bb86e6965d72/go.mod h1:2w+qxVu2KSGW78Ex/XaIqfh/OvBgjEsmN53S4T8vEyA= github.com/cppforlife/cobrautil v0.0.0-20221130162803-acdfead391ef h1:de10GNLe45JTMghl2qf9WH17H/BjGShK41X3vKAsPJA= github.com/cppforlife/cobrautil v0.0.0-20221130162803-acdfead391ef/go.mod h1:2w+qxVu2KSGW78Ex/XaIqfh/OvBgjEsmN53S4T8vEyA= github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835 h1:mYQweUIBD+TBRjIeQnJmXr0GSVMpI6O0takyb/aaOgo= github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835/go.mod h1:dYeVsKp1vvK8XjdTPR1gF+uk+9doxKeO3hqQTOCr7T4= -github.com/cppforlife/go-cli-ui v0.0.0-20200505234325-512793797f05/go.mod h1:I0qrzCmuPWYI6kAOvkllYjaW2aovclWbJ96+v+YyHb0= github.com/cppforlife/go-cli-ui v0.0.0-20220425131040-94f26b16bc14 h1:MjRdR01xh0sfkeS3OOBv+MYkYsrbHuTDc4rfBnVdFaI= github.com/cppforlife/go-cli-ui v0.0.0-20220425131040-94f26b16bc14/go.mod h1:AlgTssDlstr4mf92TR4DPITLfl5+7wEY4cKStCmeeto= github.com/cppforlife/go-patch v0.0.0-20240118020416-2147782e467b h1:+8LQctLhaj+63L/37l8IK/5Q3odN6RzWlglonUwrKok= github.com/cppforlife/go-patch v0.0.0-20240118020416-2147782e467b/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= @@ -62,22 +29,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -87,35 +46,21 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -125,73 +70,27 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hpcloud/tail v1.0.1-0.20180514194441-a1dbeea552b7/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/k14s/difflib v0.0.0-20201117154628-0c031775bf57/go.mod h1:B0xN2MiNBGWOWi9CcfAo9LBI8IU4J1utlbOIJCsmKr4= github.com/k14s/difflib v0.0.0-20240118055029-596a7a5585c3 h1:q2ikACDbDDbyUcN9JkDcNMGhIx1EBRkctAsPZMr35qM= github.com/k14s/difflib v0.0.0-20240118055029-596a7a5585c3/go.mod h1:B0xN2MiNBGWOWi9CcfAo9LBI8IU4J1utlbOIJCsmKr4= github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 h1:4bcRTTSx+LKSxMWibIwzHnDNmaN1x52oEpvnjCy+8vk= github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368/go.mod h1:lKGj1op99m4GtQISxoD2t+K+WO/q2NzEPKvfXFQfbCA= -github.com/k14s/ytt v0.36.0 h1:ERr7q+r3ziYJv91fvTx2b76d1MIo3SI/EsAS01WU+Zo= -github.com/k14s/ytt v0.36.0/go.mod h1:awQ3bHBk1qT2Xn3GJVdmaLss2khZOIBBKFd2TNXZNMk= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -201,44 +100,28 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= @@ -246,173 +129,73 @@ github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 h1:eTNDkNRNV5lZvUbVM9Nop0lBcljSnA8rZX6yQPZ0ZnU= github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11/go.mod h1:EmVJt97N+pfWFsli/ipXTBZqSG5F5KGQhm3c3IsGq1o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec/go.mod h1:wPlfmglZmRWMYv/qJy3P+fK/UnoQB5ISk4txfNd9tDo= github.com/vito/go-interact v1.0.1 h1:O8xi8c93bRUv2Tb/v6HdiuGc+WnWt+AQzF74MOOdlBs= github.com/vito/go-interact v1.0.1/go.mod h1:HrdHSJXD2yn1MhlTwSIMeFgQ5WftiIorszVGd3S/DAA= github.com/vmware-tanzu/carvel-kapp-controller v0.51.0 h1:lCCHy9n/AzWPtq5gqbINJHgmF32RCUkh9DbVQgx6HAs= github.com/vmware-tanzu/carvel-kapp-controller v0.51.0/go.mod h1:go1MQz1D2kVgjaE2ZHtuHGECFk8EDLeXMpjmDNDzuJM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180730214132-a0f8a16cb08c/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -430,32 +213,13 @@ golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -465,70 +229,32 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20140529071818-c131134a1947/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= k8s.io/apiextensions-apiserver v0.31.2 h1:W8EwUb8+WXBLu56ser5IudT2cOho0gAKeTOnywBLxd0= @@ -551,7 +277,6 @@ k8s.io/kubernetes v1.31.2 h1:VNSu4O7Xn5FFRsh9ePXyEPg6ucR21fOftarSdi053Gs= k8s.io/kubernetes v1.31.2/go.mod h1:9xmT2buyTYj8TRKwRae7FcuY8k5+xlxv7VivvO0KKfs= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/pkg/kapp/resourcesmisc/wait_rule_contract_v1.go b/pkg/kapp/resourcesmisc/wait_rule_contract_v1.go index 077247eeb..af16b0299 100644 --- a/pkg/kapp/resourcesmisc/wait_rule_contract_v1.go +++ b/pkg/kapp/resourcesmisc/wait_rule_contract_v1.go @@ -7,9 +7,9 @@ import ( "fmt" ctlres "carvel.dev/kapp/pkg/kapp/resources" - cmdtpl "github.com/k14s/ytt/pkg/cmd/template" - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" + cmdtpl "carvel.dev/ytt/pkg/cmd/template" + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" "sigs.k8s.io/yaml" ) diff --git a/pkg/kapp/yttresmod/overlay_contract_v1_mod.go b/pkg/kapp/yttresmod/overlay_contract_v1_mod.go index 091ac58c1..611777ffb 100644 --- a/pkg/kapp/yttresmod/overlay_contract_v1_mod.go +++ b/pkg/kapp/yttresmod/overlay_contract_v1_mod.go @@ -7,9 +7,9 @@ import ( "fmt" ctlres "carvel.dev/kapp/pkg/kapp/resources" - cmdtpl "github.com/k14s/ytt/pkg/cmd/template" - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" + cmdtpl "carvel.dev/ytt/pkg/cmd/template" + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" "sigs.k8s.io/yaml" ) diff --git a/vendor/github.com/k14s/ytt/LICENSE b/vendor/carvel.dev/ytt/LICENSE similarity index 100% rename from vendor/github.com/k14s/ytt/LICENSE rename to vendor/carvel.dev/ytt/LICENSE diff --git a/vendor/github.com/k14s/ytt/NOTICE b/vendor/carvel.dev/ytt/NOTICE similarity index 100% rename from vendor/github.com/k14s/ytt/NOTICE rename to vendor/carvel.dev/ytt/NOTICE diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/template/bulk_input.go b/vendor/carvel.dev/ytt/pkg/cmd/template/bulk_input.go similarity index 78% rename from vendor/github.com/k14s/ytt/pkg/cmd/template/bulk_input.go rename to vendor/carvel.dev/ytt/pkg/cmd/template/bulk_input.go index f9b50d499..df7e408c1 100644 --- a/vendor/github.com/k14s/ytt/pkg/cmd/template/bulk_input.go +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/bulk_input.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -6,9 +6,8 @@ package template import ( "encoding/json" - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" - "github.com/spf13/cobra" + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" ) type BulkFilesSourceOpts struct { @@ -16,9 +15,11 @@ type BulkFilesSourceOpts struct { bulkOut bool } -func (s *BulkFilesSourceOpts) Set(cmd *cobra.Command) { - cmd.Flags().StringVar(&s.bulkIn, "bulk-in", "", "Accept files in bulk format") - cmd.Flags().BoolVar(&s.bulkOut, "bulk-out", false, "Output files in bulk format") +// Set registers "bulk" flags and wires-up those flags up to this +// BulkFilesSourceOpts to be set when the corresponding cobra.Command is executed. +func (s *BulkFilesSourceOpts) Set(cmdFlags CmdFlags) { + cmdFlags.StringVar(&s.bulkIn, "bulk-in", "", "Accept files in bulk format") + cmdFlags.BoolVar(&s.bulkOut, "bulk-out", false, "Output files in bulk format") } type BulkFilesSource struct { diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/template/cmd.go b/vendor/carvel.dev/ytt/pkg/cmd/template/cmd.go similarity index 53% rename from vendor/github.com/k14s/ytt/pkg/cmd/template/cmd.go rename to vendor/carvel.dev/ytt/pkg/cmd/template/cmd.go index 6a130ded1..713fa2416 100644 --- a/vendor/github.com/k14s/ytt/pkg/cmd/template/cmd.go +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/cmd.go @@ -1,18 +1,24 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template import ( + "fmt" "time" - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" - "github.com/k14s/ytt/pkg/workspace" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/spf13/cobra" + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" + "carvel.dev/ytt/pkg/schema" + "carvel.dev/ytt/pkg/workspace" + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/yamlmeta" ) +// Options both contains the configuration for a "template" command AND the +// top-level implementation of that command. +// +// For most intents and purposes, RunWithFiles() is the entrypoint. type Options struct { IgnoreUnknownComments bool ImplicitMapKeyOverrides bool @@ -37,39 +43,40 @@ type Output struct { Err error } +// FileSource provides both a means of loading from sources (i.e. Input) and rendering into sinks (i.e. Output) type FileSource interface { HasInput() bool HasOutput() bool Input() (Input, error) + // Output renders the results (i.e. an instance of Output) to the configured output/sink of this FileSource Output(Output) error } var _ []FileSource = []FileSource{&BulkFilesSource{}, &RegularFilesSource{}} +// NewOptions initializes a new instance of template.Options. func NewOptions() *Options { - return &Options{} + var opts files.SymlinkAllowOpts + return &Options{ + RegularFilesSourceOpts: RegularFilesSourceOpts{SymlinkAllowOpts: &opts}, + DataValuesFlags: DataValuesFlags{SymlinkAllowOpts: &opts}, + } } -func NewCmd(o *Options) *cobra.Command { - cmd := &cobra.Command{ - Use: "template", - Aliases: []string{"t", "tpl"}, - Short: "Process YAML templates (deprecated; use top-level command -- e.g. `ytt -f-` instead of `ytt template -f-`)", - RunE: func(c *cobra.Command, args []string) error { return o.Run() }, - } - cmd.Flags().BoolVar(&o.IgnoreUnknownComments, "ignore-unknown-comments", false, +// BindFlags registers template flags for template command. +func (o *Options) BindFlags(cmdFlags CmdFlags) { + cmdFlags.BoolVar(&o.IgnoreUnknownComments, "ignore-unknown-comments", false, "Configure whether unknown comments are considered as errors (comments that do not start with '#@' or '#!')") - cmd.Flags().BoolVar(&o.ImplicitMapKeyOverrides, "implicit-map-key-overrides", false, + cmdFlags.BoolVar(&o.ImplicitMapKeyOverrides, "implicit-map-key-overrides", false, "Configure whether implicit map keys overrides are allowed") - cmd.Flags().BoolVarP(&o.StrictYAML, "strict", "s", false, "Configure to use _strict_ YAML subset") - cmd.Flags().BoolVar(&o.Debug, "debug", false, "Enable debug output") - cmd.Flags().BoolVar(&o.InspectFiles, "files-inspect", false, "Inspect files") - - o.BulkFilesSourceOpts.Set(cmd) - o.RegularFilesSourceOpts.Set(cmd) - o.FileMarksOpts.Set(cmd) - o.DataValuesFlags.Set(cmd) - return cmd + cmdFlags.BoolVarP(&o.StrictYAML, "strict", "s", false, "Configure to use _strict_ YAML subset") + cmdFlags.BoolVar(&o.Debug, "debug", false, "Enable debug output") + cmdFlags.BoolVar(&o.InspectFiles, "files-inspect", false, "Determine the set of files that would be processed and display that result") + + o.BulkFilesSourceOpts.Set(cmdFlags) + o.RegularFilesSourceOpts.Set(cmdFlags) + o.FileMarksOpts.Set(cmdFlags) + o.DataValuesFlags.Set(cmdFlags) } func (o *Options) Run() error { @@ -114,11 +121,14 @@ func (o *Options) RunWithFiles(in Input, ui ui.UI) Output { return Output{Err: err} } - libraryExecutionFactory := workspace.NewLibraryExecutionFactory(ui, workspace.TemplateLoaderOpts{ - IgnoreUnknownComments: o.IgnoreUnknownComments, - ImplicitMapKeyOverrides: o.ImplicitMapKeyOverrides, - StrictYAML: o.StrictYAML, - }) + libraryExecutionFactory := workspace.NewLibraryExecutionFactory( + ui, + workspace.TemplateLoaderOpts{ + IgnoreUnknownComments: o.IgnoreUnknownComments, + ImplicitMapKeyOverrides: o.ImplicitMapKeyOverrides, + StrictYAML: o.StrictYAML, + }, + o.DataValuesFlags.SkipValidation) libraryCtx := workspace.LibraryExecutionContext{Current: rootLibrary, Root: rootLibrary} rootLibraryExecution := libraryExecutionFactory.New(libraryCtx) @@ -128,6 +138,18 @@ func (o *Options) RunWithFiles(in Input, ui ui.UI) Output { return Output{Err: err} } + if o.DataValuesFlags.InspectSchema { + return o.inspectSchema(schema) + } + + schemaType, err := o.RegularFilesSourceOpts.OutputType.Schema() + if err != nil { + return Output{Err: err} + } + if schemaType == RegularFilesOutputTypeOpenAPI { + return Output{Err: fmt.Errorf("Output type currently only supported for data values schema (i.e. include --data-values-schema-inspect)")} + } + values, libraryValues, err := rootLibraryExecution.Values(valuesOverlays, schema) if err != nil { return Output{Err: err} @@ -136,11 +158,7 @@ func (o *Options) RunWithFiles(in Input, ui ui.UI) Output { libraryValues = append(libraryValues, libraryValuesOverlays...) if o.DataValuesFlags.Inspect { - return Output{ - DocSet: &yamlmeta.DocumentSet{ - Items: []*yamlmeta.Document{values.Doc}, - }, - } + return o.inspectDataValues(values) } result, err := rootLibraryExecution.Eval(values, libraryValues, librarySchemas) @@ -151,6 +169,31 @@ func (o *Options) RunWithFiles(in Input, ui ui.UI) Output { return Output{Files: result.Files, DocSet: result.DocSet} } +func (o *Options) inspectDataValues(values *datavalues.Envelope) Output { + return Output{ + DocSet: &yamlmeta.DocumentSet{ + Items: []*yamlmeta.Document{values.Doc}, + }, + } +} + +func (o *Options) inspectSchema(dataValuesSchema *datavalues.Schema) Output { + format, err := o.RegularFilesSourceOpts.OutputType.Schema() + if err != nil { + return Output{Err: err} + } + if format == RegularFilesOutputTypeOpenAPI { + openAPIDoc := schema.NewOpenAPIDocument(dataValuesSchema.GetDocumentType()) + return Output{ + DocSet: &yamlmeta.DocumentSet{ + Items: []*yamlmeta.Document{openAPIDoc.AsDocument()}, + }, + } + } + return Output{Err: fmt.Errorf("Data values schema export only supported in OpenAPI v3 format; specify format with --output=%s flag", + RegularFilesOutputTypeOpenAPI)} +} + func (o *Options) pickSource(srcs []FileSource, pickFunc func(FileSource) bool) FileSource { for _, src := range srcs { if pickFunc(src) { diff --git a/vendor/carvel.dev/ytt/pkg/cmd/template/cmd_flags.go b/vendor/carvel.dev/ytt/pkg/cmd/template/cmd_flags.go new file mode 100644 index 000000000..aae840202 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/cmd_flags.go @@ -0,0 +1,20 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package template + +// CmdFlags interface decouples this package from +// depending on cobra.Command/flags concrete types. +type CmdFlags interface { + BoolVar(p *bool, name string, value bool, usage string) + BoolVarP(p *bool, name, shorthand string, value bool, usage string) + + StringVar(p *string, name string, value string, usage string) + StringVarP(p *string, name, shorthand string, value string, usage string) + + StringArrayVar(p *[]string, name string, value []string, usage string) + StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) + + StringSliceVar(p *[]string, name string, value []string, usage string) + StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) +} diff --git a/vendor/carvel.dev/ytt/pkg/cmd/template/data_values_file.go b/vendor/carvel.dev/ytt/pkg/cmd/template/data_values_file.go new file mode 100644 index 000000000..5aaccba64 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/data_values_file.go @@ -0,0 +1,28 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package template + +import ( + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yttlibrary/overlay" +) + +type DataValuesFile struct { + doc *yamlmeta.Document +} + +func NewDataValuesFile(doc *yamlmeta.Document) DataValuesFile { + return DataValuesFile{doc.DeepCopy()} +} + +func (f DataValuesFile) AsOverlay() (*yamlmeta.Document, error) { + doc := f.doc.DeepCopy() + + err := overlay.AnnotateForPlainMerge(doc) + if err != nil { + return nil, err + } + + return doc, nil +} diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/template/data_values_flags.go b/vendor/carvel.dev/ytt/pkg/cmd/template/data_values_flags.go similarity index 50% rename from vendor/github.com/k14s/ytt/pkg/cmd/template/data_values_flags.go rename to vendor/carvel.dev/ytt/pkg/cmd/template/data_values_flags.go index 2ad4383e9..4f144cfed 100644 --- a/vendor/github.com/k14s/ytt/pkg/cmd/template/data_values_flags.go +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/data_values_flags.go @@ -1,26 +1,27 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template import ( "fmt" - "io/ioutil" "os" "strings" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/files" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/workspace/ref" + "carvel.dev/ytt/pkg/yamlmeta" + yttoverlay "carvel.dev/ytt/pkg/yttlibrary/overlay" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/workspace" - "github.com/k14s/ytt/pkg/yamlmeta" - yttoverlay "github.com/k14s/ytt/pkg/yttlibrary/overlay" - "github.com/spf13/cobra" ) const ( - dvsKVSep = "=" - dvsMapKeySep = "." + dvsKVSep = "=" + dvsMapKeySep = "." + libraryKeySep = ":" ) type DataValuesFlags struct { @@ -33,23 +34,30 @@ type DataValuesFlags struct { FromFiles []string - Inspect bool + Inspect bool + InspectSchema bool + SkipValidation bool - EnvironFunc func() []string - ReadFileFunc func(string) ([]byte, error) -} + EnvironFunc func() []string + ReadFilesFunc func(paths string) ([]*files.File, error) -func (s *DataValuesFlags) Set(cmd *cobra.Command) { - cmd.Flags().StringArrayVar(&s.EnvFromStrings, "data-values-env", nil, "Extract data values (as strings) from prefixed env vars (format: PREFIX for PREFIX_all__key1=str) (can be specified multiple times)") - cmd.Flags().StringArrayVar(&s.EnvFromYAML, "data-values-env-yaml", nil, "Extract data values (parsed as YAML) from prefixed env vars (format: PREFIX for PREFIX_all__key1=true) (can be specified multiple times)") + *files.SymlinkAllowOpts +} - cmd.Flags().StringArrayVarP(&s.KVsFromStrings, "data-value", "v", nil, "Set specific data value to given value, as string (format: all.key1.subkey=123) (can be specified multiple times)") - cmd.Flags().StringArrayVar(&s.KVsFromYAML, "data-value-yaml", nil, "Set specific data value to given value, parsed as YAML (format: all.key1.subkey=true) (can be specified multiple times)") - cmd.Flags().StringArrayVar(&s.KVsFromFiles, "data-value-file", nil, "Set specific data value to given file contents, as string (format: all.key1.subkey=/file/path) (can be specified multiple times)") +// Set registers data values ingestion flags and wires-up those flags up to this +// DataValuesFlags to be set when the corresponding cobra.Command is executed. +func (s *DataValuesFlags) Set(cmdFlags CmdFlags) { + cmdFlags.StringArrayVar(&s.EnvFromStrings, "data-values-env", nil, "Extract data values (as strings) from prefixed env vars (format: PREFIX for PREFIX_all__key1=str) (can be specified multiple times)") + cmdFlags.StringArrayVar(&s.EnvFromYAML, "data-values-env-yaml", nil, "Extract data values (parsed as YAML) from prefixed env vars (format: PREFIX for PREFIX_all__key1=true) (can be specified multiple times)") - cmd.Flags().StringArrayVar(&s.FromFiles, "data-values-file", nil, "Set multiple data values via a YAML file (format: /file/path.yml) (can be specified multiple times)") + cmdFlags.StringArrayVarP(&s.KVsFromStrings, "data-value", "v", nil, "Set specific data value to given value, as string (format: all.key1.subkey=123) (can be specified multiple times)") + cmdFlags.StringArrayVar(&s.KVsFromYAML, "data-value-yaml", nil, "Set specific data value to given value, parsed as YAML (format: all.key1.subkey=true) (can be specified multiple times)") + cmdFlags.StringArrayVar(&s.KVsFromFiles, "data-value-file", nil, "Set specific data value to contents of a file (format: [@lib1:]all.key1.subkey={file path, HTTP URL, or '-' (i.e. stdin)}) (can be specified multiple times)") + cmdFlags.StringArrayVar(&s.FromFiles, "data-values-file", nil, "Set multiple data values via plain YAML files (format: [@lib1:]{file path, HTTP URL, or '-' (i.e. stdin)}) (can be specified multiple times)") - cmd.Flags().BoolVar(&s.Inspect, "data-values-inspect", false, "Inspect data values") + cmdFlags.BoolVar(&s.Inspect, "data-values-inspect", false, "Determine the final data values (applying any overlays) and display that result") + cmdFlags.BoolVar(&s.SkipValidation, "dangerous-data-values-disable-validation", false, "Skip validating data values (not recommended: may result in templates failing or invalid output)") + cmdFlags.BoolVar(&s.InspectSchema, "data-values-schema-inspect", false, "Determine the complete schema for data values (applying any overlays) and display the result (only OpenAPI v3.0 is supported, see --output)") } type dataValuesFlagsSource struct { @@ -60,7 +68,11 @@ type dataValuesFlagsSource struct { type valueTransformFunc func(string) (interface{}, error) -func (s *DataValuesFlags) AsOverlays(strict bool) ([]*workspace.DataValues, []*workspace.DataValues, error) { +// AsOverlays generates Data Values overlays, one for each setting in this DataValuesFlags. +// +// Returns a collection of overlays targeted for the root library and a separate collection of overlays "addressed" to +// children libraries. +func (s *DataValuesFlags) AsOverlays(strict bool) ([]*datavalues.Envelope, []*datavalues.Envelope, error) { plainValFunc := func(rawVal string) (interface{}, error) { return rawVal, nil } yamlValFunc := func(rawVal string) (interface{}, error) { @@ -71,7 +83,7 @@ func (s *DataValuesFlags) AsOverlays(strict bool) ([]*workspace.DataValues, []*w return val, nil } - var result []*workspace.DataValues + var result []*datavalues.Envelope // Files go first for _, file := range s.FromFiles { @@ -115,8 +127,8 @@ func (s *DataValuesFlags) AsOverlays(strict bool) ([]*workspace.DataValues, []*w result = append(result, val) } - var overlayValues []*workspace.DataValues - var libraryOverlays []*workspace.DataValues + var overlayValues []*datavalues.Envelope + var libraryOverlays []*datavalues.Envelope for _, doc := range result { if doc.IntendedForAnotherLibrary() { libraryOverlays = append(libraryOverlays, doc) @@ -128,53 +140,62 @@ func (s *DataValuesFlags) AsOverlays(strict bool) ([]*workspace.DataValues, []*w return overlayValues, libraryOverlays, nil } -func (s *DataValuesFlags) file(path string, strict bool) ([]*workspace.DataValues, error) { - libRef, path, err := s.libraryRefAndKey(path) +func (s *DataValuesFlags) file(fullPath string, strict bool) ([]*datavalues.Envelope, error) { + libRef, path, err := s.libraryRefAndRemainder(fullPath) if err != nil { return nil, err } - contents, err := s.readFile(path) + dvFiles, err := s.asFiles(path) if err != nil { - return nil, fmt.Errorf("Reading file '%s'", path) - } - - docSetOpts := yamlmeta.DocSetOpts{ - AssociatedName: path, - Strict: strict, + return nil, fmt.Errorf("Find files '%s': %s", path, err) } - docSet, err := yamlmeta.NewDocumentSetFromBytes(contents, docSetOpts) - if err != nil { - return nil, fmt.Errorf("Unmarshaling YAML data values file '%s': %s", path, err) - } + var result []*datavalues.Envelope + for _, dvFile := range dvFiles { + // Users may want to store other files (docs, etc.) within this directory; ignore those. + if dvFile.IsImplied() && !(dvFile.Type() == files.TypeYAML) { + continue + } + contents, err := dvFile.Bytes() + if err != nil { + return nil, fmt.Errorf("Reading file '%s': %s", dvFile.RelativePath(), err) + } - var result []*workspace.DataValues + docSetOpts := yamlmeta.DocSetOpts{ + AssociatedName: dvFile.RelativePath(), + Strict: strict, + } + docSet, err := yamlmeta.NewDocumentSetFromBytes(contents, docSetOpts) + if err != nil { + return nil, fmt.Errorf("Unmarshaling YAML data values file '%s': %s", dvFile.Description(), err) + } - for _, doc := range docSet.Items { - if doc.Value != nil { - dvsOverlay, err := NewDataValuesFile(doc).AsOverlay() - if err != nil { - return nil, fmt.Errorf("Checking data values file '%s': %s", path, err) - } - dvs, err := workspace.NewDataValuesWithOptionalLib(dvsOverlay, libRef) - if err != nil { - return nil, err + for _, doc := range docSet.Items { + if doc.Value != nil { + dvsOverlay, err := NewDataValuesFile(doc).AsOverlay() + if err != nil { + return nil, fmt.Errorf("Checking data values file '%s': %s", path, err) + } + dvs, err := datavalues.NewEnvelopeWithLibRef(dvsOverlay, libRef) + if err != nil { + return nil, err + } + result = append(result, dvs) } - result = append(result, dvs) } } return result, nil } -func (s *DataValuesFlags) env(prefix string, src dataValuesFlagsSource) ([]*workspace.DataValues, error) { +func (s *DataValuesFlags) env(prefix string, src dataValuesFlagsSource) ([]*datavalues.Envelope, error) { const ( envKeyPrefix = "_" envMapKeySep = "__" ) - result := []*workspace.DataValues{} + result := []*datavalues.Envelope{} envVars := os.Environ() if s.EnvironFunc != nil { @@ -206,7 +227,7 @@ func (s *DataValuesFlags) env(prefix string, src dataValuesFlagsSource) ([]*work desc := fmt.Sprintf("(%s arg) %s", src.Name, keyPrefix) overlay := s.buildOverlay(keyPieces, val, desc, envVar) - dvs, err := workspace.NewDataValuesWithOptionalLib(overlay, libRef) + dvs, err := datavalues.NewEnvelopeWithLibRef(overlay, libRef) if err != nil { return nil, err } @@ -217,7 +238,7 @@ func (s *DataValuesFlags) env(prefix string, src dataValuesFlagsSource) ([]*work return result, nil } -func (s *DataValuesFlags) kv(kv string, src dataValuesFlagsSource) (*workspace.DataValues, error) { +func (s *DataValuesFlags) kv(kv string, src dataValuesFlagsSource) (*datavalues.Envelope, error) { pieces := strings.SplitN(kv, dvsKVSep, 2) if len(pieces) != 2 { return nil, fmt.Errorf("Expected format key=value") @@ -235,7 +256,7 @@ func (s *DataValuesFlags) kv(kv string, src dataValuesFlagsSource) (*workspace.D desc := fmt.Sprintf("(%s arg)", src.Name) overlay := s.buildOverlay(strings.Split(key, dvsMapKeySep), val, desc, kv) - return workspace.NewDataValuesWithOptionalLib(overlay, libRef) + return datavalues.NewEnvelopeWithLibRef(overlay, libRef) } func (s *DataValuesFlags) parseYAML(data string, strict bool) (interface{}, error) { @@ -246,13 +267,21 @@ func (s *DataValuesFlags) parseYAML(data string, strict bool) (interface{}, erro return docSet.Items[0].Value, nil } -func (s *DataValuesFlags) kvFile(kv string) (*workspace.DataValues, error) { +func (s *DataValuesFlags) kvFile(kv string) (*datavalues.Envelope, error) { pieces := strings.SplitN(kv, dvsKVSep, 2) if len(pieces) != 2 { return nil, fmt.Errorf("Expected format key=/file/path") } - contents, err := s.readFile(pieces[1]) + dvFile, err := s.asFiles(pieces[1]) + if err != nil { + return nil, fmt.Errorf("Finding file '%s': %s", pieces[1], err) + } + if len(dvFile) > 1 { + return nil, fmt.Errorf("Expected '%s' to be a file, but is a directory", pieces[1]) + } + + contents, err := dvFile[0].Bytes() if err != nil { return nil, fmt.Errorf("Reading file '%s'", pieces[1]) } @@ -264,29 +293,39 @@ func (s *DataValuesFlags) kvFile(kv string) (*workspace.DataValues, error) { desc := fmt.Sprintf("(data-value-file arg) %s=%s", key, pieces[1]) overlay := s.buildOverlay(strings.Split(key, dvsMapKeySep), string(contents), desc, string(contents)) - return workspace.NewDataValuesWithOptionalLib(overlay, libRef) + return datavalues.NewEnvelopeWithLibRef(overlay, libRef) } -func (DataValuesFlags) libraryRefAndKey(key string) (string, string, error) { - const ( - libraryKeySep = ":" - ) - - keyPieces := strings.Split(key, libraryKeySep) - - switch len(keyPieces) { - case 1: - return "", key, nil +// libraryRefAndKey separates a library reference and a key and validates that no libraryKeySep exist in the key. +// libraryKeySep is disallowed in data value flag keys. +func (DataValuesFlags) libraryRefAndKey(arg string) (string, string, error) { + libRef, key, err := DataValuesFlags{}.libraryRefAndRemainder(arg) + if err != nil { + return "", "", err + } + if len(strings.Split(key, libraryKeySep)) > 1 { + // error on a common syntax mistake + return "", "", fmt.Errorf("Expected at most one library-key separator '%s' in '%s'", libraryKeySep, key) + } + return libRef, key, nil +} - case 2: - if len(keyPieces[0]) == 0 { - return "", "", fmt.Errorf("Expected library ref to not be empty") +// libraryRefAndRemainder separates a library reference prefix from the remainder of the string. +// A library reference starts with ref.LibrarySep, and ends with the first occurrence of libraryKeySep. +func (DataValuesFlags) libraryRefAndRemainder(arg string) (string, string, error) { + if strings.HasPrefix(arg, ref.LibrarySep) { + strPieces := strings.SplitN(arg, libraryKeySep, 2) + switch len(strPieces) { + case 1: + return "", arg, nil + case 2: + if len(strPieces[0]) == 1 { + return "", "", fmt.Errorf("Expected library ref to not be empty") + } + return strPieces[0], strPieces[1], nil } - return keyPieces[0], keyPieces[1], nil - - default: - return "", "", fmt.Errorf("Expected at most one library-key separator '%s' in '%s'", libraryKeySep, key) } + return "", arg, nil } func (s *DataValuesFlags) buildOverlay(keyPieces []string, value interface{}, desc string, line string) *yamlmeta.Document { @@ -294,8 +333,7 @@ func (s *DataValuesFlags) buildOverlay(keyPieces []string, value interface{}, de currMap := resultMap var lastMapItem *yamlmeta.MapItem - pos := filepos.NewPosition(1) - pos.SetFile(desc) + pos := filepos.NewPositionInFile(1, desc) pos.SetLine(line) for _, piece := range keyPieces { @@ -332,9 +370,13 @@ func (s *DataValuesFlags) buildOverlay(keyPieces []string, value interface{}, de return &yamlmeta.Document{Value: resultMap, Position: pos} } -func (s *DataValuesFlags) readFile(path string) ([]byte, error) { - if s.ReadFileFunc != nil { - return s.ReadFileFunc(path) +// asFiles enumerates the files that are found at "path" +// +// If a DataValuesFlags.ReadFilesFunc has been injected, that service is used. +// Otherwise, uses files.NewSortedFilesFromPaths() is used. +func (s *DataValuesFlags) asFiles(path string) ([]*files.File, error) { + if s.ReadFilesFunc != nil { + return s.ReadFilesFunc(path) } - return ioutil.ReadFile(path) + return files.NewSortedFilesFromPaths([]string{path}, *s.SymlinkAllowOpts) } diff --git a/vendor/carvel.dev/ytt/pkg/cmd/template/doc.go b/vendor/carvel.dev/ytt/pkg/cmd/template/doc.go new file mode 100644 index 000000000..ce8b6212c --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/doc.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package template implements the "template" command (not to be confused with +"pkg/template" home of the templating mechanism itself). + +Front-and-center is template.Options. This is both the host of ytt settings +parsed from the command-line through Cobra AND the top-level logic that +implements the command. +*/ +package template diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/template/file_marks.go b/vendor/carvel.dev/ytt/pkg/cmd/template/file_marks.go similarity index 88% rename from vendor/github.com/k14s/ytt/pkg/cmd/template/file_marks.go rename to vendor/carvel.dev/ytt/pkg/cmd/template/file_marks.go index dcd43095f..6c4ea7c76 100644 --- a/vendor/github.com/k14s/ytt/pkg/cmd/template/file_marks.go +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/file_marks.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -8,16 +8,17 @@ import ( "regexp" "strings" - "github.com/k14s/ytt/pkg/files" - "github.com/spf13/cobra" + "carvel.dev/ytt/pkg/files" ) type FileMarksOpts struct { FileMarks []string } -func (s *FileMarksOpts) Set(cmd *cobra.Command) { - cmd.Flags().StringArrayVar(&s.FileMarks, "file-mark", nil, "File mark (ie change file path, mark as non-template) (format: file:key=value) (can be specified multiple times)") +// Set registers file mark flags and wires-up those flags up to this +// FileMarksOpts to be set when the corresponding cobra.Command is executed. +func (s *FileMarksOpts) Set(cmdFlags CmdFlags) { + cmdFlags.StringArrayVar(&s.FileMarks, "file-mark", nil, "File mark (ie change file path, mark as non-template) (format: file:key=value) (can be specified multiple times)") } func (s *FileMarksOpts) Apply(filesToProcess []*files.File) ([]*files.File, error) { diff --git a/vendor/carvel.dev/ytt/pkg/cmd/template/regular_input.go b/vendor/carvel.dev/ytt/pkg/cmd/template/regular_input.go new file mode 100644 index 000000000..2d08a8664 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/cmd/template/regular_input.go @@ -0,0 +1,186 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package template + +import ( + "fmt" + "io" + "strings" + + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" + "carvel.dev/ytt/pkg/yamlmeta" +) + +// RegularFilesSourceOpts holds configuration for when regular files are the input/output +// of the execution (via the --files and --output... flags). +type RegularFilesSourceOpts struct { + files []string + + outputDir string + OutputFiles string + OutputType OutputType + + *files.SymlinkAllowOpts +} + +// OutputType holds the user's desire for two (2) categories of output: +// - file format type :: yaml, json, pos +// - schema type :: OpenAPI V3, ytt Schema +type OutputType struct { + Types []string +} + +// Set registers flags related to sourcing ordinary files/directories and wires-up those flags up to this +// RegularFilesSourceOpts to be set when the corresponding cobra.Command is executed. +func (s *RegularFilesSourceOpts) Set(cmdFlags CmdFlags) { + cmdFlags.StringArrayVarP(&s.files, "file", "f", nil, "File(s) to process {filepath, HTTP URL, or '-' (i.e. stdin)} (can be specified multiple times)") + + cmdFlags.StringVar(&s.outputDir, "dangerous-emptied-output-directory", "", + "Delete given directory, and then create it with output files") + cmdFlags.StringVar(&s.OutputFiles, "output-files", "", "Add output files to given directory") + + cmdFlags.StringSliceVarP(&s.OutputType.Types, "output", "o", []string{RegularFilesOutputTypeYAML}, + fmt.Sprintf("Configure output format. Can specify file format (%s) and/or schema type (%s) (can be specified multiple times)", + strings.Join(RegularFilesOutputFormatTypes, ", "), + strings.Join(RegularFilesOutputSchemaTypes, ", "))) + + cmdFlags.BoolVar(&s.SymlinkAllowOpts.AllowAll, "dangerous-allow-all-symlink-destinations", false, + "Symlinks to all destinations are allowed") + cmdFlags.StringSliceVar(&s.SymlinkAllowOpts.AllowedDstPaths, "allow-symlink-destination", nil, + "File paths to which symlinks are allowed (can be specified multiple times)") +} + +type RegularFilesSource struct { + opts RegularFilesSourceOpts + ui ui.UI +} + +func NewRegularFilesSource(opts RegularFilesSourceOpts, ui ui.UI) *RegularFilesSource { + return &RegularFilesSource{opts, ui} +} + +func (s *RegularFilesSource) HasInput() bool { return len(s.opts.files) > 0 } +func (s *RegularFilesSource) HasOutput() bool { return true } + +func (s *RegularFilesSource) Input() (Input, error) { + filesToProcess, err := files.NewSortedFilesFromPaths(s.opts.files, *s.opts.SymlinkAllowOpts) + if err != nil { + return Input{}, err + } + + return Input{Files: filesToProcess}, nil +} + +func (s *RegularFilesSource) Output(out Output) error { + if out.Err != nil { + return out.Err + } + + nonYamlFileNames := []string{} + switch { + case len(s.opts.outputDir) > 0: + return files.NewOutputDirectory(s.opts.outputDir, out.Files, s.ui).Write() + case len(s.opts.OutputFiles) > 0: + return files.NewOutputDirectory(s.opts.OutputFiles, out.Files, s.ui).WriteFiles() + default: + for _, file := range out.Files { + if file.Type() != files.TypeYAML { + nonYamlFileNames = append(nonYamlFileNames, file.RelativePath()) + } + } + } + + var printerFunc func(io.Writer) yamlmeta.DocumentPrinter + + outputType, err := s.opts.OutputType.Format() + if err != nil { + return err + } + + switch outputType { + case RegularFilesOutputTypeYAML: + printerFunc = nil + case RegularFilesOutputTypeJSON: + printerFunc = func(w io.Writer) yamlmeta.DocumentPrinter { return yamlmeta.NewJSONPrinter(w) } + case RegularFilesOutputTypePos: + printerFunc = func(w io.Writer) yamlmeta.DocumentPrinter { + return yamlmeta.WrappedFilePositionPrinter{yamlmeta.NewFilePositionPrinter(w)} + } + } + + combinedDocBytes, err := out.DocSet.AsBytesWithPrinter(printerFunc) + if err != nil { + return fmt.Errorf("Marshaling combined template result: %s", err) + } + + s.ui.Debugf("### result\n") + s.ui.Printf("%s", combinedDocBytes) // no newline + + if len(nonYamlFileNames) > 0 { + s.ui.Warnf("\n" + `Warning: Found Non-YAML templates in input. Non-YAML templates are not rendered to standard output. +If you want to include those results, use the --output-files or --dangerous-emptied-output-directory flag.` + "\n") + } + return nil +} + +// When the FileSource are RegularFilesSource, indicates which file format to use when rendering the output. +const ( + RegularFilesOutputTypeYAML = "yaml" + RegularFilesOutputTypeJSON = "json" + RegularFilesOutputTypePos = "pos" +) + +// When the FileSource are RegularFilesSource, indicates which schema type to use when rendering the output. +const ( + RegularFilesOutputTypeOpenAPI = "openapi-v3" + RegularFilesOutputTypeNone = "" +) + +// Collections of each category of output type +var ( + RegularFilesOutputFormatTypes = []string{RegularFilesOutputTypeYAML, RegularFilesOutputTypeJSON, RegularFilesOutputTypePos} + RegularFilesOutputSchemaTypes = []string{RegularFilesOutputTypeOpenAPI} + RegularFilesOutputTypes = append(RegularFilesOutputFormatTypes, RegularFilesOutputSchemaTypes...) +) + +// Format returns which of the file format types is in effect +func (o *OutputType) Format() (string, error) { + return o.typeFrom(RegularFilesOutputFormatTypes, RegularFilesOutputTypeYAML) +} + +// Schema returns which of the schema types is in effect +func (o *OutputType) Schema() (string, error) { + return o.typeFrom(RegularFilesOutputSchemaTypes, RegularFilesOutputTypeNone) +} + +func (o *OutputType) typeFrom(types []string, defaultValue string) (string, error) { + if err := o.validateTypes(); err != nil { + return "", err + } + for _, t := range o.Types { + if o.stringInSlice(t, types) { + return t, nil + } + } + return defaultValue, nil +} + +func (o *OutputType) validateTypes() error { + for _, t := range o.Types { + if !o.stringInSlice(t, RegularFilesOutputTypes) { + return fmt.Errorf("Unknown output type '%v'", t) + } + } + return nil +} + +func (o *OutputType) stringInSlice(target string, slice []string) bool { + for _, s := range slice { + if target == s { + return true + } + } + return false +} diff --git a/vendor/carvel.dev/ytt/pkg/cmd/ui/doc.go b/vendor/carvel.dev/ytt/pkg/cmd/ui/doc.go new file mode 100644 index 000000000..ad6ba4eee --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/cmd/ui/doc.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package ui provides a thin abstraction over user input and output (typically, +a tty device). +*/ +package ui diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/ui/tty.go b/vendor/carvel.dev/ytt/pkg/cmd/ui/tty.go similarity index 96% rename from vendor/github.com/k14s/ytt/pkg/cmd/ui/tty.go rename to vendor/carvel.dev/ytt/pkg/cmd/ui/tty.go index 235773c13..d5065f764 100644 --- a/vendor/github.com/k14s/ytt/pkg/cmd/ui/tty.go +++ b/vendor/carvel.dev/ytt/pkg/cmd/ui/tty.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package ui diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/ui/ui.go b/vendor/carvel.dev/ytt/pkg/cmd/ui/ui.go similarity index 85% rename from vendor/github.com/k14s/ytt/pkg/cmd/ui/ui.go rename to vendor/carvel.dev/ytt/pkg/cmd/ui/ui.go index 88851fa7c..ebc09e639 100644 --- a/vendor/github.com/k14s/ytt/pkg/cmd/ui/ui.go +++ b/vendor/carvel.dev/ytt/pkg/cmd/ui/ui.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package ui diff --git a/vendor/carvel.dev/ytt/pkg/filepos/doc.go b/vendor/carvel.dev/ytt/pkg/filepos/doc.go new file mode 100644 index 000000000..fd02a1efd --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/filepos/doc.go @@ -0,0 +1,16 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package filepos provides the concept of Position: a source name (usually a file) +and line number within that source. + +File positions are crucial when reporting errors to the user. It is often +even more useful to share the actual source line as well. For this reason +Position also contains a cached copy of the source line at the Position. + +Not all Position point within a file (e.g. code that is generated). The +zero-value of Position (can be created using NewUnknownPosition()) represents +this case. +*/ +package filepos diff --git a/vendor/github.com/k14s/ytt/pkg/filepos/position.go b/vendor/carvel.dev/ytt/pkg/filepos/position.go similarity index 74% rename from vendor/github.com/k14s/ytt/pkg/filepos/position.go rename to vendor/carvel.dev/ytt/pkg/filepos/position.go index aae36671c..d81d4d6da 100644 --- a/vendor/github.com/k14s/ytt/pkg/filepos/position.go +++ b/vendor/carvel.dev/ytt/pkg/filepos/position.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package filepos @@ -22,17 +22,27 @@ func NewPosition(lineNum int) *Position { return &Position{lineNum: &lineNum, known: true} } +// NewPositionInFile returns the Position of line "lineNum" within the file "file" +func NewPositionInFile(lineNum int, file string) *Position { + p := NewPosition(lineNum) + p.file = file + return p +} + // NewUnknownPosition is equivalent of zero value *Position func NewUnknownPosition() *Position { return &Position{} } +// NewUnknownPositionInFile produces a Position of a known file at an unknown line. +func NewUnknownPositionInFile(file string) *Position { + return &Position{file: file} +} + func NewUnknownPositionWithKeyVal(k, v interface{}, separator string) *Position { return &Position{line: fmt.Sprintf("%v%v %#v", k, separator, v), fromMemory: true} } -func (p *Position) SetFile(file string) { p.file = file } - func (p *Position) SetLine(line string) { p.line = line } func (p *Position) IsKnown() bool { return p != nil && p.known } @@ -109,3 +119,16 @@ func (p *Position) DeepCopyWithLineOffset(offset int) *Position { *newPos.lineNum += offset return newPos } + +// IsNextTo compares the location of one position with another. +func (p *Position) IsNextTo(otherPosition *Position) bool { + if p.IsKnown() && otherPosition.IsKnown() { + if p.GetFile() == otherPosition.GetFile() { + diff := p.LineNum() - otherPosition.LineNum() + if -1 <= diff && 1 >= diff { + return true + } + } + } + return false +} diff --git a/vendor/carvel.dev/ytt/pkg/files/doc.go b/vendor/carvel.dev/ytt/pkg/files/doc.go new file mode 100644 index 000000000..fc60118a0 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/files/doc.go @@ -0,0 +1,15 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package files provides primitives for enumerating and loading data from various +file or file-like Source's and for writing output to filesystem files and +directories. + +This allows the rest of ytt code to process logically chunked streams of data +without becoming entangled in the details of how to read or write data. + +ytt processes files differently depending on their Type. For example, +File instances that are TypeYAML are parsed as YAML. +*/ +package files diff --git a/vendor/github.com/k14s/ytt/pkg/files/file.go b/vendor/carvel.dev/ytt/pkg/files/file.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/files/file.go rename to vendor/carvel.dev/ytt/pkg/files/file.go index 9be81954e..accfe7cd2 100644 --- a/vendor/github.com/k14s/ytt/pkg/files/file.go +++ b/vendor/carvel.dev/ytt/pkg/files/file.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package files @@ -233,6 +233,12 @@ func (r *File) isTemplate() bool { return !r.IsLibrary() && (t == TypeYAML || t == TypeText) } +// IsImplied reports whether this file was implicitly included (found within an explicitly named directory) or not +// (named explicitly as input). +func (r *File) IsImplied() bool { + return strings.ContainsRune(r.OriginalRelativePath(), os.PathSeparator) +} + func (r *File) IsLibrary() bool { exts := strings.Split(filepath.Base(r.RelativePath()), ".") @@ -240,8 +246,8 @@ func (r *File) IsLibrary() bool { return true } - // make exception for starlark files as they are just pure code - return r.matchesExt(starlarkExts) + // Starlark files are always libraries + return r.Type() == TypeStarlark } func (r *File) matchesExt(exts []string) bool { diff --git a/vendor/github.com/k14s/ytt/pkg/files/output_directory.go b/vendor/carvel.dev/ytt/pkg/files/output_directory.go similarity index 95% rename from vendor/github.com/k14s/ytt/pkg/files/output_directory.go rename to vendor/carvel.dev/ytt/pkg/files/output_directory.go index e8ce17ad4..4e1add2a3 100644 --- a/vendor/github.com/k14s/ytt/pkg/files/output_directory.go +++ b/vendor/carvel.dev/ytt/pkg/files/output_directory.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package files @@ -8,7 +8,7 @@ import ( "os" "strings" - "github.com/k14s/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/cmd/ui" ) var ( diff --git a/vendor/github.com/k14s/ytt/pkg/files/output_file.go b/vendor/carvel.dev/ytt/pkg/files/output_file.go similarity index 96% rename from vendor/github.com/k14s/ytt/pkg/files/output_file.go rename to vendor/carvel.dev/ytt/pkg/files/output_file.go index 0b4784b36..774e5aee9 100644 --- a/vendor/github.com/k14s/ytt/pkg/files/output_file.go +++ b/vendor/carvel.dev/ytt/pkg/files/output_file.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package files diff --git a/vendor/github.com/k14s/ytt/pkg/files/sources.go b/vendor/carvel.dev/ytt/pkg/files/sources.go similarity index 83% rename from vendor/github.com/k14s/ytt/pkg/files/sources.go rename to vendor/carvel.dev/ytt/pkg/files/sources.go index 6573eca7c..9c01f9457 100644 --- a/vendor/github.com/k14s/ytt/pkg/files/sources.go +++ b/vendor/carvel.dev/ytt/pkg/files/sources.go @@ -1,11 +1,11 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package files import ( "fmt" - "io/ioutil" + "io" "net/http" "os" "path" @@ -40,7 +40,7 @@ type StdinSource struct { func NewStdinSource() StdinSource { // only read stdin once - bs, err := ioutil.ReadAll(os.Stdin) + bs, err := ReadStdin() return StdinSource{bs, err} } @@ -55,7 +55,8 @@ type LocalSource struct { func NewLocalSource(path, dir string) LocalSource { return LocalSource{path, dir} } -func (s LocalSource) Description() string { return fmt.Sprintf("file '%s'", s.path) } +// Description return LocalSource's (i.e. file's) path +func (s LocalSource) Description() string { return fmt.Sprintf("file %s", s.path) } func (s LocalSource) RelativePath() (string, error) { if s.dir == "" { @@ -81,13 +82,16 @@ func (s LocalSource) RelativePath() (string, error) { return "", fmt.Errorf("unknown relative path for %s", s.path) } -func (s LocalSource) Bytes() ([]byte, error) { return ioutil.ReadFile(s.path) } +// Bytes returns bytes of the read file +func (s LocalSource) Bytes() ([]byte, error) { return os.ReadFile(s.path) } type HTTPSource struct { - url string + url string + Client *http.Client } -func NewHTTPSource(path string) HTTPSource { return HTTPSource{path} } +// NewHTTPSource returns a new source of type HTTP +func NewHTTPSource(path string) HTTPSource { return HTTPSource{path, &http.Client{}} } func (s HTTPSource) Description() string { return fmt.Sprintf("HTTP URL '%s'", s.url) @@ -96,14 +100,18 @@ func (s HTTPSource) Description() string { func (s HTTPSource) RelativePath() (string, error) { return path.Base(s.url), nil } func (s HTTPSource) Bytes() ([]byte, error) { - resp, err := http.Get(s.url) + resp, err := s.Client.Get(s.url) if err != nil { return nil, fmt.Errorf("Requesting URL '%s': %s", s.url, err) } defer resp.Body.Close() - result, err := ioutil.ReadAll(resp.Body) + if resp.StatusCode < 200 || resp.StatusCode > 299 { + return nil, fmt.Errorf("Requesting URL '%s': %s", s.url, resp.Status) + } + + result, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("Reading URL '%s': %s", s.url, err) } diff --git a/vendor/carvel.dev/ytt/pkg/files/stdin.go b/vendor/carvel.dev/ytt/pkg/files/stdin.go new file mode 100644 index 000000000..aaad8cf55 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/files/stdin.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package files + +import ( + "fmt" + "io" + "os" +) + +var hasStdinBeenRead bool + +// ReadStdin only read stdin once +func ReadStdin() ([]byte, error) { + if hasStdinBeenRead { + return nil, fmt.Errorf("Standard input has already been read, has the '-' argument been used in more than one flag?") + } + hasStdinBeenRead = true + return io.ReadAll(os.Stdin) +} diff --git a/vendor/github.com/k14s/ytt/pkg/files/symlink.go b/vendor/carvel.dev/ytt/pkg/files/symlink.go similarity index 91% rename from vendor/github.com/k14s/ytt/pkg/files/symlink.go rename to vendor/carvel.dev/ytt/pkg/files/symlink.go index 056fe8613..41992a0a4 100644 --- a/vendor/github.com/k14s/ytt/pkg/files/symlink.go +++ b/vendor/carvel.dev/ytt/pkg/files/symlink.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package files @@ -47,7 +47,7 @@ func (s Symlink) IsAllowed(opts SymlinkAllowOpts) error { } } - return fmt.Errorf("Expected symlink file '%s' -> '%s' to be allowed, but was not", s.path, dstPath) + return fmt.Errorf("Expected symlink file '%s' -> '%s' to be allowed, but was not (hint: symlinks are disallowed as a security feature, use '--allow-symlink-destination' flags to override)", s.path, dstPath) } func (s Symlink) isIn(path, allowedPath string) (bool, error) { diff --git a/vendor/github.com/k14s/ytt/pkg/orderedmap/convert.go b/vendor/carvel.dev/ytt/pkg/orderedmap/convert.go similarity index 81% rename from vendor/github.com/k14s/ytt/pkg/orderedmap/convert.go rename to vendor/carvel.dev/ytt/pkg/orderedmap/convert.go index c29db025e..174c45d0d 100644 --- a/vendor/github.com/k14s/ytt/pkg/orderedmap/convert.go +++ b/vendor/carvel.dev/ytt/pkg/orderedmap/convert.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package orderedmap @@ -70,11 +70,21 @@ func (c Conversion) fromUnorderedMaps(object interface{}) interface{} { panic("Expected map[interface{}]interface{} instead of *unordered.Map in fromUnorderedMaps") case []interface{}: + result := make([]interface{}, len(typedObj)) for i, item := range typedObj { - typedObj[i] = c.fromUnorderedMaps(item) + result[i] = c.fromUnorderedMaps(item) } - return typedObj + return result + // some sources (e.g. toml library) yield specific type of slices. + // slices in Go are not covariant, so each flavor of slice must have its own case, here. + // process these exactly the same way we do for generic slices (prior case) + case []map[string]interface{}: + result := make([]interface{}, len(typedObj)) + for i, item := range typedObj { + result[i] = c.fromUnorderedMaps(item) + } + return result default: return typedObj } diff --git a/vendor/carvel.dev/ytt/pkg/orderedmap/doc.go b/vendor/carvel.dev/ytt/pkg/orderedmap/doc.go new file mode 100644 index 000000000..00fe68e9b --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/orderedmap/doc.go @@ -0,0 +1,11 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package orderedmap provides a map implementation where the order of keys is +maintained (unlike the native Go map). + +This flavor of map is crucial in keeping the output of ytt deterministic and +stable. +*/ +package orderedmap diff --git a/vendor/github.com/k14s/ytt/pkg/orderedmap/map.go b/vendor/carvel.dev/ytt/pkg/orderedmap/map.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/orderedmap/map.go rename to vendor/carvel.dev/ytt/pkg/orderedmap/map.go index 661662d7b..ec716851c 100644 --- a/vendor/github.com/k14s/ytt/pkg/orderedmap/map.go +++ b/vendor/carvel.dev/ytt/pkg/orderedmap/map.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package orderedmap diff --git a/vendor/carvel.dev/ytt/pkg/schema/annotations.go b/vendor/carvel.dev/ytt/pkg/schema/annotations.go new file mode 100644 index 000000000..410ac8904 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/annotations.go @@ -0,0 +1,775 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + "strings" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/validations" + "carvel.dev/ytt/pkg/yamlmeta" + "github.com/k14s/starlark-go/starlark" +) + +// Declare @schema/... annotation names +const ( + AnnotationNullable template.AnnotationName = "schema/nullable" + AnnotationType template.AnnotationName = "schema/type" + AnnotationDefault template.AnnotationName = "schema/default" + AnnotationDescription template.AnnotationName = "schema/desc" + AnnotationTitle template.AnnotationName = "schema/title" + AnnotationExamples template.AnnotationName = "schema/examples" + AnnotationDeprecated template.AnnotationName = "schema/deprecated" + TypeAnnotationKwargAny string = "any" + AnnotationValidation template.AnnotationName = "schema/validation" +) + +type Annotation interface { + NewTypeFromAnn() (Type, error) + GetPosition() *filepos.Position +} + +type TypeAnnotation struct { + any bool + node yamlmeta.Node + pos *filepos.Position +} + +type NullableAnnotation struct { + node yamlmeta.Node + pos *filepos.Position +} + +// DefaultAnnotation is a wrapper for a value provided via @schema/default annotation +type DefaultAnnotation struct { + val interface{} + pos *filepos.Position +} + +// DescriptionAnnotation documents the purpose of a node +type DescriptionAnnotation struct { + description string + pos *filepos.Position +} + +// TitleAnnotation provides title of a node +type TitleAnnotation struct { + title string + pos *filepos.Position +} + +// DeprecatedAnnotation is a wrapper for a value provided via @schema/deprecated annotation +type DeprecatedAnnotation struct { + notice string + pos *filepos.Position +} + +// ExampleAnnotation provides the Examples of a node +type ExampleAnnotation struct { + examples []Example + pos *filepos.Position +} + +// ValidationAnnotation is a wrapper for validations provided via @schema/validation annotation +type ValidationAnnotation struct { + validation *validations.NodeValidation + pos *filepos.Position +} + +// Example contains a yaml example and its description +type Example struct { + description string + example interface{} +} + +// documentation holds metadata about a Type, provided via documentation annotations +type documentation struct { + title string + description string + deprecated bool + deprecationNotice string + examples []Example +} + +// NewTypeAnnotation checks the keyword argument provided via @schema/type annotation, and returns wrapper for the annotated node. +func NewTypeAnnotation(ann template.NodeAnnotation, node yamlmeta.Node) (*TypeAnnotation, error) { + if len(ann.Kwargs) == 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + description: fmt.Sprintf("expected @%v annotation to have keyword argument and value", AnnotationType), + expected: "valid keyword argument and value", + found: fmt.Sprintf("missing keyword argument and value (by %s)", ann.Position.AsCompactString()), + hints: []string{fmt.Sprintf("Supported key-value pairs are '%v=True', '%v=False'", TypeAnnotationKwargAny, TypeAnnotationKwargAny)}, + } + } + typeAnn := &TypeAnnotation{node: node, pos: ann.Position} + for _, kwarg := range ann.Kwargs { + argName, err := core.NewStarlarkValue(kwarg[0]).AsString() + if err != nil { + return nil, err + } + + switch argName { + case TypeAnnotationKwargAny: + isAnyType, err := core.NewStarlarkValue(kwarg[1]).AsBool() + if err != nil { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + description: "unknown @schema/type annotation keyword argument", + expected: "starlark.Bool", + found: fmt.Sprintf("%T (by %s)", kwarg[1], ann.Position.AsCompactString()), + hints: []string{fmt.Sprintf("Supported kwargs are '%v'", TypeAnnotationKwargAny)}, + } + } + typeAnn.any = isAnyType + + default: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + description: "unknown @schema/type annotation keyword argument", + expected: "A valid kwarg", + found: fmt.Sprintf("%s (by %s)", argName, ann.Position.AsCompactString()), + hints: []string{fmt.Sprintf("Supported kwargs are '%v'", TypeAnnotationKwargAny)}, + } + } + } + return typeAnn, nil +} + +// NewNullableAnnotation checks that there are no arguments, and returns wrapper for the annotated node. +func NewNullableAnnotation(ann template.NodeAnnotation, node yamlmeta.Node) (*NullableAnnotation, error) { + if len(ann.Kwargs) != 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + description: fmt.Sprintf("expected @%v annotation to not contain any keyword arguments", AnnotationNullable), + expected: "starlark.Bool", + found: fmt.Sprintf("keyword argument in @%v (by %v)", AnnotationNullable, ann.Position.AsCompactString()), + hints: []string{fmt.Sprintf("Supported kwargs are '%v'", TypeAnnotationKwargAny)}, + } + } + + return &NullableAnnotation{node, ann.Position}, nil +} + +// NewDeprecatedAnnotation validates the value from the AnnotationDeprecated, and returns the value +func NewDeprecatedAnnotation(ann template.NodeAnnotation, pos *filepos.Position) (*DeprecatedAnnotation, error) { + if len(ann.Kwargs) != 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDeprecated), + expected: "string", + found: fmt.Sprintf("keyword argument in @%v (by %v)", AnnotationDeprecated, ann.Position.AsCompactString()), + hints: []string{"this annotation only accepts one argument: a string."}, + } + } + switch numArgs := len(ann.Args); { + case numArgs == 0: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDeprecated), + expected: "string", + found: fmt.Sprintf("missing value in @%v (by %v)", AnnotationDeprecated, ann.Position.AsCompactString()), + } + case numArgs > 1: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDeprecated), + expected: "string", + found: fmt.Sprintf("%v values in @%v (by %v)", numArgs, AnnotationDeprecated, ann.Position.AsCompactString()), + } + } + + strVal, err := core.NewStarlarkValue(ann.Args[0]).AsString() + if err != nil { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDeprecated), + expected: "string", + found: fmt.Sprintf("Non-string value in @%v (by %v)", AnnotationDeprecated, ann.Position.AsCompactString()), + } + } + return &DeprecatedAnnotation{strVal, ann.Position}, nil +} + +// NewDefaultAnnotation checks the argument provided via @schema/default annotation, and returns wrapper for that value. +func NewDefaultAnnotation(ann template.NodeAnnotation, effectiveType Type, pos *filepos.Position) (*DefaultAnnotation, error) { + if len(ann.Kwargs) != 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDefault), + expected: fmt.Sprintf("%s (by %s)", effectiveType.String(), effectiveType.GetDefinitionPosition().AsCompactString()), + found: fmt.Sprintf("keyword argument in @%v (by %v)", AnnotationDefault, ann.Position.AsCompactString()), + hints: []string{ + "this annotation only accepts one argument: the default value.", + "value must be in Starlark format, e.g.: {'key': 'value'}, True."}, + } + } + switch numArgs := len(ann.Args); { + case numArgs == 0: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDefault), + expected: fmt.Sprintf("%s (by %s)", effectiveType.String(), effectiveType.GetDefinitionPosition().AsCompactString()), + found: fmt.Sprintf("missing value in @%v (by %v)", AnnotationDefault, ann.Position.AsCompactString()), + } + case numArgs > 1: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDefault), + expected: fmt.Sprintf("%s (by %s)", effectiveType.String(), effectiveType.GetDefinitionPosition().AsCompactString()), + found: fmt.Sprintf("%v values in @%v (by %v)", numArgs, AnnotationDefault, ann.Position.AsCompactString()), + } + } + + val, err := core.NewStarlarkValue(ann.Args[0]).AsGoValue() + if err != nil { + // at this point the annotation is processed, and the Starlark evaluated + panic(err) + } + return &DefaultAnnotation{yamlmeta.NewASTFromInterfaceWithPosition(val, pos), ann.Position}, nil +} + +// NewDescriptionAnnotation validates the value from the AnnotationDescription, and returns the value +func NewDescriptionAnnotation(ann template.NodeAnnotation, pos *filepos.Position) (*DescriptionAnnotation, error) { + if len(ann.Kwargs) != 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDescription), + expected: "string", + found: fmt.Sprintf("keyword argument in @%v (by %v)", AnnotationDescription, ann.Position.AsCompactString()), + hints: []string{"this annotation only accepts one argument: a string."}, + } + } + switch numArgs := len(ann.Args); { + case numArgs == 0: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDescription), + expected: "string", + found: fmt.Sprintf("missing value in @%v (by %v)", AnnotationDescription, ann.Position.AsCompactString()), + } + case numArgs > 1: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDescription), + expected: "string", + found: fmt.Sprintf("%v values in @%v (by %v)", numArgs, AnnotationDescription, ann.Position.AsCompactString()), + } + } + + strVal, err := core.NewStarlarkValue(ann.Args[0]).AsString() + if err != nil { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationDescription), + expected: "string", + found: fmt.Sprintf("Non-string value in @%v (by %v)", AnnotationDescription, ann.Position.AsCompactString()), + } + } + return &DescriptionAnnotation{strVal, ann.Position}, nil +} + +// NewTitleAnnotation validates the value from the AnnotationTitle, and returns the value +func NewTitleAnnotation(ann template.NodeAnnotation, pos *filepos.Position) (*TitleAnnotation, error) { + if len(ann.Kwargs) != 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationTitle), + expected: "string", + found: fmt.Sprintf("keyword argument in @%v (by %v)", AnnotationTitle, ann.Position.AsCompactString()), + hints: []string{"this annotation only accepts one argument: a string."}, + } + } + switch numArgs := len(ann.Args); { + case numArgs == 0: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationTitle), + expected: "string", + found: fmt.Sprintf("missing value in @%v (by %v)", AnnotationTitle, ann.Position.AsCompactString()), + } + case numArgs > 1: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationTitle), + expected: "string", + found: fmt.Sprintf("%v values in @%v (by %v)", numArgs, AnnotationTitle, ann.Position.AsCompactString()), + } + } + + strVal, err := core.NewStarlarkValue(ann.Args[0]).AsString() + if err != nil { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationTitle), + expected: "string", + found: fmt.Sprintf("Non-string value in @%v (by %v)", AnnotationTitle, ann.Position.AsCompactString()), + } + } + return &TitleAnnotation{strVal, ann.Position}, nil +} + +// NewExampleAnnotation validates the value(s) from the AnnotationExamples, and returns the value(s) +func NewExampleAnnotation(ann template.NodeAnnotation, pos *filepos.Position) (*ExampleAnnotation, error) { + if len(ann.Kwargs) != 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("keyword argument in @%v (by %v)", AnnotationExamples, ann.Position.AsCompactString()), + } + } + if len(ann.Args) == 0 { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("missing value in @%v (by %v)", AnnotationExamples, ann.Position.AsCompactString()), + } + } + + var examples []Example + for _, ex := range ann.Args { + exampleTuple, ok := ex.(starlark.Tuple) + if !ok { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("%v for @%v (at %v)", ex.Type(), AnnotationExamples, ann.Position.AsCompactString()), + } + } + switch { + case len(exampleTuple) == 0: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("empty tuple in @%v (by %v)", AnnotationExamples, ann.Position.AsCompactString()), + } + case len(exampleTuple) == 1: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("empty tuple in @%v (by %v)", AnnotationExamples, ann.Position.AsCompactString()), + } + case len(exampleTuple) > 2: + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("%v-tuple argument in @%v (by %v)", len(exampleTuple), AnnotationExamples, ann.Position.AsCompactString()), + } + default: + description, err := core.NewStarlarkValue(exampleTuple[0]).AsString() + if err != nil { + return nil, schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: pos, + description: fmt.Sprintf("syntax error in @%v annotation", AnnotationExamples), + expected: "2-tuple containing description (string) and example value (of expected type)", + found: fmt.Sprintf("%v value for @%v (at %v)", exampleTuple[0].Type(), AnnotationExamples, ann.Position.AsCompactString()), + } + } + exampleVal, err := core.NewStarlarkValue(exampleTuple[1]).AsGoValue() + if err != nil { + panic(err) + } + examples = append(examples, Example{description, yamlmeta.NewASTFromInterfaceWithPosition(exampleVal, pos)}) + } + } + return &ExampleAnnotation{examples, ann.Position}, nil +} + +// NewValidationAnnotation checks the values provided via @schema/validation annotation, and returns wrapper for the validation defined +func NewValidationAnnotation(ann template.NodeAnnotation) (*ValidationAnnotation, error) { + validation, err := validations.NewValidationFromAnn(ann) + if err != nil { + return nil, fmt.Errorf("Invalid @%s annotation - %s", AnnotationValidation, err.Error()) + } + + return &ValidationAnnotation{validation, ann.Position}, nil +} + +// NewTypeFromAnn returns type information given by annotation. +func (t *TypeAnnotation) NewTypeFromAnn() (Type, error) { + if t.any { + return &AnyType{defaultValue: t.node.GetValues()[0], Position: t.node.GetPosition()}, nil + } + return nil, nil +} + +// NewTypeFromAnn returns type information given by annotation. +func (n *NullableAnnotation) NewTypeFromAnn() (Type, error) { + inferredType, err := InferTypeFromValue(n.node.GetValues()[0], n.node.GetPosition()) + if err != nil { + return nil, err + } + return &NullType{ValueType: inferredType, Position: n.node.GetPosition()}, nil +} + +// NewTypeFromAnn returns type information given by annotation. +func (d *DefaultAnnotation) NewTypeFromAnn() (Type, error) { + return nil, nil +} + +// NewTypeFromAnn returns type information given by annotation. +func (e *ExampleAnnotation) NewTypeFromAnn() (Type, error) { + return nil, nil +} + +// NewTypeFromAnn returns type information given by annotation. DeprecatedAnnotation has no type information. +func (d *DeprecatedAnnotation) NewTypeFromAnn() (Type, error) { + return nil, nil +} + +// NewTypeFromAnn returns type information given by annotation. DescriptionAnnotation has no type information. +func (d *DescriptionAnnotation) NewTypeFromAnn() (Type, error) { + return nil, nil +} + +// NewTypeFromAnn returns type information given by annotation. TitleAnnotation has no type information. +func (t *TitleAnnotation) NewTypeFromAnn() (Type, error) { + return nil, nil +} + +// NewTypeFromAnn returns type information given by annotation. +func (v *ValidationAnnotation) NewTypeFromAnn() (Type, error) { + return nil, nil +} + +// GetPosition returns position of the source comment used to create this annotation. +func (n *NullableAnnotation) GetPosition() *filepos.Position { + return n.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (t *TypeAnnotation) GetPosition() *filepos.Position { + return t.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (d *DefaultAnnotation) GetPosition() *filepos.Position { + return d.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (d *DeprecatedAnnotation) GetPosition() *filepos.Position { + return d.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (d *DescriptionAnnotation) GetPosition() *filepos.Position { + return d.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (e *ExampleAnnotation) GetPosition() *filepos.Position { + return e.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (t *TitleAnnotation) GetPosition() *filepos.Position { + return t.pos +} + +// GetPosition returns position of the source comment used to create this annotation. +func (v *ValidationAnnotation) GetPosition() *filepos.Position { + return nil +} + +// GetValidation gets the NodeValidation created from @schema/validation annotation +func (v *ValidationAnnotation) GetValidation() *validations.NodeValidation { + return v.validation +} + +func (t *TypeAnnotation) IsAny() bool { + return t.any +} + +// Val returns default value specified in annotation. +func (d *DefaultAnnotation) Val() interface{} { + return d.val +} + +func collectTypeAnnotations(node yamlmeta.Node) ([]Annotation, error) { + var anns []Annotation + + for _, annotation := range []template.AnnotationName{AnnotationType, AnnotationNullable} { + ann, err := processOptionalAnnotation(node, annotation, nil) + if err != nil { + return nil, err + } + if ann != nil { + anns = append(anns, ann) + } + } + return anns, nil +} + +func collectValueAnnotations(node yamlmeta.Node, effectiveType Type) ([]Annotation, error) { + var anns []Annotation + + for _, annotation := range []template.AnnotationName{AnnotationNullable, AnnotationDefault} { + ann, err := processOptionalAnnotation(node, annotation, effectiveType) + if err != nil { + return nil, err + } + if ann != nil { + anns = append(anns, ann) + } + } + return anns, nil +} + +// collectDocumentationAnnotations provides annotations that are used for documentation purposes +func collectDocumentationAnnotations(node yamlmeta.Node) ([]Annotation, error) { + var anns []Annotation + + for _, annotation := range []template.AnnotationName{AnnotationDescription, AnnotationTitle, AnnotationExamples, AnnotationDeprecated} { + ann, err := processOptionalAnnotation(node, annotation, nil) + if err != nil { + return nil, err + } + if ann != nil { + anns = append(anns, ann) + } + } + return anns, nil +} + +func processOptionalAnnotation(node yamlmeta.Node, optionalAnnotation template.AnnotationName, effectiveType Type) (Annotation, error) { + nodeAnnotations := template.NewAnnotations(node) + + if nodeAnnotations.Has(optionalAnnotation) { + ann := nodeAnnotations[optionalAnnotation] + + switch optionalAnnotation { + case AnnotationNullable: + nullAnn, err := NewNullableAnnotation(ann, node) + if err != nil { + return nil, err + } + return nullAnn, nil + case AnnotationType: + typeAnn, err := NewTypeAnnotation(ann, node) + if err != nil { + return nil, err + } + return typeAnn, nil + case AnnotationDefault: + switch node.(type) { + case *yamlmeta.DocumentSet, *yamlmeta.Array, *yamlmeta.Map: + return nil, NewSchemaError(fmt.Sprintf("Invalid schema - @%v not supported on %s", AnnotationDefault, yamlmeta.TypeName(node)), + schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + }) + case *yamlmeta.ArrayItem: + return nil, NewSchemaError(fmt.Sprintf("Invalid schema - @%v not supported on array item", AnnotationDefault), + schemaAssertionError{ + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + hints: []string{"do you mean to set a default value for the array?", "set an array's default by annotating its parent."}, + }) + } + defaultAnn, err := NewDefaultAnnotation(ann, effectiveType, node.GetPosition()) + if err != nil { + return nil, err + } + return defaultAnn, nil + case AnnotationDeprecated: + if _, ok := node.(*yamlmeta.Document); ok { + return nil, schemaAssertionError{ + description: fmt.Sprintf("@%v not supported on a %s", AnnotationDeprecated, yamlmeta.TypeName(node)), + annPositions: []*filepos.Position{ann.Position}, + position: node.GetPosition(), + hints: []string{"do you mean to deprecate the entire schema document?", "use schema/deprecated on individual keys."}, + } + } + deprAnn, err := NewDeprecatedAnnotation(ann, node.GetPosition()) + if err != nil { + return nil, err + } + return deprAnn, nil + case AnnotationDescription: + descAnn, err := NewDescriptionAnnotation(ann, node.GetPosition()) + if err != nil { + return nil, err + } + return descAnn, nil + case AnnotationExamples: + exampleAnn, err := NewExampleAnnotation(ann, node.GetPosition()) + if err != nil { + return nil, err + } + return exampleAnn, nil + case AnnotationTitle: + titleAnn, err := NewTitleAnnotation(ann, node.GetPosition()) + if err != nil { + return nil, err + } + return titleAnn, nil + } + } + + return nil, nil +} + +func processValidationAnnotation(node yamlmeta.Node) (*ValidationAnnotation, error) { + nodeAnnotations := template.NewAnnotations(node) + if nodeAnnotations.Has(AnnotationValidation) { + validationAnn, err := NewValidationAnnotation(nodeAnnotations[AnnotationValidation]) + if err != nil { + return nil, err + } + return validationAnn, nil + } + return nil, nil +} + +func getTypeFromAnnotations(anns []Annotation) (Type, error) { + annsCopy := append([]Annotation{}, anns...) + + var typeFromAnn Type + for _, ann := range annsCopy { + switch typedAnn := ann.(type) { + case *TypeAnnotation: + if typedAnn.IsAny() { + var err error + typeFromAnn, err = typedAnn.NewTypeFromAnn() + if err != nil { + return nil, err + } + } + case *NullableAnnotation: + if typeFromAnn == nil { + var err error + typeFromAnn, err = typedAnn.NewTypeFromAnn() + if err != nil { + return nil, err + } + } else { + typeFromAnn.SetDefaultValue(nil) + } + default: + continue + } + } + + return typeFromAnn, nil +} + +func setDocumentationFromAnns(docAnns []Annotation, typeOfValue Type) error { + for _, a := range docAnns { + switch ann := a.(type) { + case *TitleAnnotation: + typeOfValue.SetTitle(ann.title) + case *DescriptionAnnotation: + typeOfValue.SetDescription(ann.description) + case *DeprecatedAnnotation: + typeOfValue.SetDeprecated(true, ann.notice) + case *ExampleAnnotation: + err := checkExamplesValue(ann, typeOfValue) + if err != nil { + return err + } + typeOfValue.SetExamples(ann.examples) + } + } + return nil +} + +func checkExamplesValue(ann *ExampleAnnotation, typeOfValue Type) error { + var typeCheck TypeCheck + for _, ex := range ann.examples { + if node, ok := ex.example.(yamlmeta.Node); ok { + defaultValue := node.DeepCopyAsNode() + chk := typeOfValue.AssignTypeTo(defaultValue) + if !chk.HasViolations() { + chk = CheckNode(defaultValue) + } + typeCheck.Violations = append(typeCheck.Violations, chk.Violations...) + } else { + chk := typeOfValue.CheckType(&yamlmeta.MapItem{Value: ex.example, Position: typeOfValue.GetDefinitionPosition()}) + typeCheck.Violations = append(typeCheck.Violations, chk.Violations...) + } + } + if typeCheck.HasViolations() { + var violations []error + // add violating annotation position to error + for _, err := range typeCheck.Violations { + if typeCheckAssertionErr, ok := err.(schemaAssertionError); ok { + typeCheckAssertionErr.annPositions = []*filepos.Position{ann.GetPosition()} + typeCheckAssertionErr.found = typeCheckAssertionErr.found + fmt.Sprintf(" (by %v)", ann.GetPosition().AsCompactString()) + violations = append(violations, typeCheckAssertionErr) + } else { + violations = append(violations, err) + } + } + return NewSchemaError(fmt.Sprintf("Invalid schema - @%v has wrong type", AnnotationExamples), violations...) + } + return nil +} + +type checkForAnnotations struct{} + +// Visit if `node` is annotated with `@schema/nullable`, `@schema/type`, or `@schema/default` (AnnotationNullable, AnnotationType, AnnotationDefault). +// Used when checking a node's children for undesired annotations. +// +// This visitor returns an error if any listed annotation is found, +// otherwise it will return nil. +func (c checkForAnnotations) Visit(n yamlmeta.Node) error { + var foundAnns []string + var foundAnnsPos []*filepos.Position + nodeAnnotations := template.NewAnnotations(n) + for _, annName := range []template.AnnotationName{AnnotationNullable, AnnotationType, AnnotationDefault} { + if nodeAnnotations.Has(annName) { + foundAnns = append(foundAnns, string(annName)) + foundAnnsPos = append(foundAnnsPos, nodeAnnotations[annName].Position) + } + } + if len(foundAnnsPos) > 0 { + foundText := strings.Join(foundAnns, ", @") + return NewSchemaError("Invalid schema", schemaAssertionError{ + annPositions: foundAnnsPos, + position: n.GetPosition(), + description: "Schema was specified within an \"any type\" fragment", + expected: "no '@schema/...' on nodes within a node annotated '@schema/type any=True'", + found: fmt.Sprintf("@%v annotation(s)", foundText), + hints: []string{"an \"any type\" fragment has no constraints; nested schema annotations conflict and are disallowed"}, + }) + } + + return nil +} diff --git a/vendor/carvel.dev/ytt/pkg/schema/assign.go b/vendor/carvel.dev/ytt/pkg/schema/assign.go new file mode 100644 index 000000000..ca7bab169 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/assign.go @@ -0,0 +1,176 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + + "carvel.dev/ytt/pkg/validations" + "carvel.dev/ytt/pkg/yamlmeta" +) + +// AssignTypeTo assigns this schema metadata to `node`. +// +// If `node` is not a yamlmeta.Document, `chk` contains a violation describing the mismatch +// If `node`'s value is not of the same structure (i.e. yamlmeta.Node type), `chk` contains a violation describing this mismatch +func (t *DocumentType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + doc, ok := node.(*yamlmeta.Document) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, t)) + return chk + } + SetType(doc, t) + valueNode, isNode := doc.Value.(yamlmeta.Node) + if isNode { + childCheck := t.ValueType.AssignTypeTo(valueNode) + chk.Violations = append(chk.Violations, childCheck.Violations...) + } // else, is a scalar + return chk +} + +// AssignTypeTo assigns this schema metadata to `node`. +// +// If `node` is not a yamlmeta.Map, `chk` contains a violation describing the mismatch +// If `node`'s yamlmeta.MapItem's cannot be assigned their corresponding MapItemType, `chk` contains a violation describing the mismatch +// If `node` is missing any yamlmeta.MapItem's specified in this MapType, they are added to `node`. +func (m *MapType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + mapNode, ok := node.(*yamlmeta.Map) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, m)) + return chk + } + var foundKeys []interface{} + SetType(node, m) + for _, mapItem := range mapNode.Items { + for _, itemType := range m.Items { + if mapItem.Key == itemType.Key { + foundKeys = append(foundKeys, itemType.Key) + childCheck := itemType.AssignTypeTo(mapItem) + chk.Violations = append(chk.Violations, childCheck.Violations...) + break + } + } + } + + m.applySchemaDefaults(foundKeys, chk, mapNode) + return chk +} + +func (m *MapType) applySchemaDefaults(foundKeys []interface{}, chk TypeCheck, mapNode *yamlmeta.Map) { + for _, item := range m.Items { + if contains(foundKeys, item.Key) { + continue + } + + val := item.GetDefaultValue() + childCheck := item.AssignTypeTo(val.(*yamlmeta.MapItem)) + chk.Violations = append(chk.Violations, childCheck.Violations...) + err := mapNode.AddValue(val) + if err != nil { + panic(fmt.Sprintf("Internal inconsistency: adding map item: %s", err)) + } + } +} + +func contains(haystack []interface{}, needle interface{}) bool { + for _, key := range haystack { + if key == needle { + return true + } + } + return false +} + +// AssignTypeTo assigns this schema metadata to `node`. +// +// If `node` is not a yamlmeta.MapItem, `chk` contains a violation describing the mismatch +// If `node`'s value is not of the same structure (i.e. yamlmeta.Node type), `chk` contains a violation describing this mismatch +func (t *MapItemType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + mapItem, ok := node.(*yamlmeta.MapItem) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, t)) + return chk + } + SetType(node, t) + valueNode, isNode := mapItem.Value.(yamlmeta.Node) + if isNode { + childCheck := t.ValueType.AssignTypeTo(valueNode) + chk.Violations = append(chk.Violations, childCheck.Violations...) + } // else, is scalar + return chk +} + +// AssignTypeTo assigns this schema metadata to `node`. +// +// If `node` is not a yamlmeta.Array, `chk` contains a violation describing the mismatch +// For each `node`'s yamlmeta.ArrayItem's that cannot be assigned this ArrayType's ArrayItemType, `chk` contains a violation describing the mismatch +func (a *ArrayType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + arrayNode, ok := node.(*yamlmeta.Array) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, a)) + return chk + } + SetType(node, a) + for _, arrayItem := range arrayNode.Items { + childCheck := a.ItemsType.AssignTypeTo(arrayItem) + chk.Violations = append(chk.Violations, childCheck.Violations...) + } + return chk +} + +// AssignTypeTo assigns this schema metadata to `node`. +// +// If `node` is not a yamlmeta.ArrayItem, `chk` contains a violation describing the mismatch +// If `node`'s value is not of the same structure (i.e. yamlmeta.Node type), `chk` contains a violation describing this mismatch +func (a *ArrayItemType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + arrayItem, ok := node.(*yamlmeta.ArrayItem) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, a)) + return chk + } + SetType(node, a) + valueNode, isNode := arrayItem.Value.(yamlmeta.Node) + if isNode { + childCheck := a.ValueType.AssignTypeTo(valueNode) + chk.Violations = append(chk.Violations, childCheck.Violations...) + } // else, is scalar + return chk +} + +// AssignTypeTo returns a violation describing the type mismatch, given that ScalarType will never accept a yamlmeta.Node +func (s *ScalarType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + return TypeCheck{[]error{NewMismatchedTypeAssertionError(node, s)}} +} + +// AssignTypeTo is a no-op given that AnyType allows all types. +func (a AnyType) AssignTypeTo(yamlmeta.Node) TypeCheck { + return TypeCheck{} +} + +// AssignTypeTo assigns this NullType's wrapped Type to `node`. +func (n NullType) AssignTypeTo(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + childCheck := n.ValueType.AssignTypeTo(node) + chk.Violations = append(chk.Violations, childCheck.Violations...) + return chk +} + +// AssignSchemaValidations implements the visitor interface to set validations from the schema type +type AssignSchemaValidations struct{} + +// Visit Extracts the validations from Node's Type and sets them in Node's meta +// This visitor returns nil if node has no assigned type or when the execution is completed +func (AssignSchemaValidations) Visit(node yamlmeta.Node) error { + if schemaType := GetType(node); schemaType != nil { + if v := schemaType.GetValidation(); v != nil { + validations.Set(node, []validations.NodeValidation{*v}) + } + } + return nil +} diff --git a/vendor/carvel.dev/ytt/pkg/schema/check.go b/vendor/carvel.dev/ytt/pkg/schema/check.go new file mode 100644 index 000000000..46e3d9cae --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/check.go @@ -0,0 +1,251 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + + "carvel.dev/ytt/pkg/yamlmeta" +) + +// CheckNode attempts type check of root node and its children. +// +// If `n` has "schema/type" metadata (typically attached using SetType()), `n` is checked against that schema, recursively. +// `chk` contains all the type violations found in the check. +func CheckNode(n yamlmeta.Node) TypeCheck { + checker := newTypeChecker() + + err := yamlmeta.Walk(n, checker) + if err != nil { + panic(err) + } + + return *checker.chk +} + +// TypeCheck is the result of checking a yamlmeta.Node structure against a given Type, recursively. +type TypeCheck struct { + Violations []error +} + +// Error generates the error message composed of the total set of TypeCheck.Violations. +func (tc TypeCheck) Error() string { + if !tc.HasViolations() { + return "" + } + + msg := "" + for _, err := range tc.Violations { + msg += err.Error() + "\n" + } + return msg +} + +// HasViolations indicates whether this TypeCheck contains any violations. +func (tc *TypeCheck) HasViolations() bool { + return len(tc.Violations) > 0 +} + +func newTypeChecker() *typeChecker { + return &typeChecker{chk: &TypeCheck{}} +} + +type typeChecker struct { + chk *TypeCheck +} + +func (t *typeChecker) Visit(node yamlmeta.Node) error { + nodeType := GetType(node) + if nodeType == nil { + return nil + } + + chk := nodeType.CheckType(node) + if chk.HasViolations() { + t.chk.Violations = append(t.chk.Violations, chk.Violations...) + } + + return nil +} + +var _ yamlmeta.Visitor = &typeChecker{} + +// CheckType checks the type of `node` against this DocumentType. +// +// If `node` is not a yamlmeta.Document, `chk` contains a violation describing this mismatch +// If this document's value is a scalar, checks its type against this DocumentType.ValueType +func (t *DocumentType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + doc, ok := node.(*yamlmeta.Document) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, t)) + return chk + } + + if _, isNode := doc.Value.(yamlmeta.Node); !isNode { + valChk := t.ValueType.CheckType(doc) // ScalarType checks doc.Value + if valChk.HasViolations() { + chk.Violations = append(chk.Violations, valChk.Violations...) + } + } + return chk +} + +// CheckType checks the type of `node` against this MapType. +// +// If `node` is not a yamlmeta.Map, `chk` contains a violation describing this mismatch +// If a contained yamlmeta.MapItem is not allowed by this MapType, `chk` contains a corresponding violation +func (m *MapType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + nodeMap, ok := node.(*yamlmeta.Map) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, m)) + return chk + } + + for _, item := range nodeMap.Items { + if !m.AllowsKey(item.Key) { + chk.Violations = append(chk.Violations, NewUnexpectedKeyAssertionError(item, m.Position, m.AllowedKeys())) + } + } + return chk +} + +// AllowsKey determines whether this MapType permits a MapItem with the key of `key` +func (m *MapType) AllowsKey(key interface{}) bool { + for _, item := range m.Items { + if item.Key == key { + return true + } + } + return false +} + +// AllowedKeys returns the set of keys (in string format) permitted in this map. +func (m *MapType) AllowedKeys() []string { + var keysAsString []string + + for _, item := range m.Items { + keysAsString = append(keysAsString, fmt.Sprintf("%s", item.Key)) + } + + return keysAsString +} + +// CheckType checks the type of `node` against this MapItemType. +// +// If `node` is not a yamlmeta.MapItem, `chk` contains a violation describing this mismatch +// If this map item's value is a scalar, checks its type against this MapItemType.ValueType +func (t *MapItemType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + mapItem, ok := node.(*yamlmeta.MapItem) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, t)) + return chk + } + + if _, isNode := mapItem.Value.(yamlmeta.Node); !isNode { + valChk := t.ValueType.CheckType(mapItem) // ScalarType checks mapItem.Value + if valChk.HasViolations() { + chk.Violations = append(chk.Violations, valChk.Violations...) + } + } + return chk +} + +// CheckType checks the type of `node` against this ArrayType +// +// If `node` is not a yamlmeta.Array, `chk` contains a violation describing the mismatch +func (a *ArrayType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + _, ok := node.(*yamlmeta.Array) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, a)) + } + return chk +} + +// CheckType checks the type of `node` against this ArrayItemType. +// +// If `node` is not a yamlmeta.ArrayItem, `chk` contains a violation describing this mismatch +// If this array item's value is a scalar, checks its type against this ArrayItemType.ValueType +func (a *ArrayItemType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + arrayItem, ok := node.(*yamlmeta.ArrayItem) + if !ok { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, a)) + return chk + } + + if _, isNode := arrayItem.Value.(yamlmeta.Node); !isNode { + valChk := a.ValueType.CheckType(arrayItem) // ScalarType checks arrayItem.Value + if valChk.HasViolations() { + chk.Violations = append(chk.Violations, valChk.Violations...) + } + } + return chk +} + +// CheckType checks the type of `node`'s `value`, which is expected to be a scalar type. +// +// If the value is not a recognized scalar type, `chk` contains a corresponding violation +// If the value is not of the type specified in this ScalarType, `chk` contains a violation describing the mismatch +func (s *ScalarType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + if len(node.GetValues()) < 1 { + panic(fmt.Sprintf("Expected a node that could hold a scalar value, but was %#v", node)) + } + value := node.GetValues()[0] + switch value.(type) { + case string: + if s.ValueType != StringType { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, s)) + } + case float64: + if s.ValueType != FloatType { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, s)) + } + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + if s.ValueType != IntType && s.ValueType != FloatType { + // integers between -9007199254740992 and 9007199254740992 fits in a float64 with no loss of precision. + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, s)) + } + case bool: + if s.ValueType != BoolType { + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, s)) + } + default: + chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(node, s)) + } + return chk +} + +// CheckType is a no-op because AnyType allows any value. +// +// Always returns an empty TypeCheck. +func (a AnyType) CheckType(_ yamlmeta.Node) TypeCheck { + return TypeCheck{} +} + +// CheckType checks the type of `node` against this NullType +// +// If `node`'s value is null, this check passes +// If `node`'s value is not null, then it is checked against this NullType's wrapped Type. +func (n NullType) CheckType(node yamlmeta.Node) TypeCheck { + chk := TypeCheck{} + node, isNode := node.(yamlmeta.Node) + if !isNode { + if node == nil { + return chk + } + } + if len(node.GetValues()) == 1 && node.GetValues()[0] == nil { + return chk + } + + check := n.GetValueType().CheckType(node) + chk.Violations = check.Violations + + return chk +} diff --git a/vendor/carvel.dev/ytt/pkg/schema/doc.go b/vendor/carvel.dev/ytt/pkg/schema/doc.go new file mode 100644 index 000000000..fb4e458dc --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/doc.go @@ -0,0 +1,31 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package schema enhances yamlmeta.Node structures with fine-grain data types. + +# Type and Checking + +Within a schema document (which itself is a yamlmeta.Document), type metadata is +attached to nodes via @schema/... annotations. Those annotations are parsed and +digested into a composite tree of schema.Type. + +With such a schema.Type hierarchy in hand, other YAML documents can be +"typed" (via Type.AssignTypeTo()). This process walks the target +yamlmeta.Document and attaches the corresponding type as metadata on each +corresponding yamlmeta.Node. + +"Typed" documents can then be "checked" (via schema.CheckNode()) to determine if +their fine-grain types conform to the assigned schema. + +# Documenting + +Other @schema/... annotations are used to describe the exact syntax and semantic +of values. + +# Other Schema Formats + +Like other Carvel tools, ytt aims to interoperate well with other tooling. In +this vein, ytt can export schema defined within ytt as an OpenAPI v3 document. +*/ +package schema diff --git a/vendor/github.com/k14s/ytt/pkg/schema/error.go b/vendor/carvel.dev/ytt/pkg/schema/error.go similarity index 53% rename from vendor/github.com/k14s/ytt/pkg/schema/error.go rename to vendor/carvel.dev/ytt/pkg/schema/error.go index 39133b8e5..3ae4b95a8 100644 --- a/vendor/github.com/k14s/ytt/pkg/schema/error.go +++ b/vendor/carvel.dev/ytt/pkg/schema/error.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package schema @@ -7,34 +7,39 @@ import ( "bytes" "fmt" "log" + "sort" "strings" "text/template" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/spell" + "carvel.dev/ytt/pkg/yamlmeta" ) const schemaErrorReportTemplate = ` {{- if .Summary}} {{.Summary}} {{addBreak .Summary}} -{{- end}} +{{ end}} {{- range .AssertionFailures}} {{- if .Description}} {{.Description}} {{- end}} {{- if .FromMemory}} - {{.SourceName}}: {{pad "#" ""}} {{pad "#" ""}} {{.Source}} {{pad "#" ""}} {{- else}} - {{.FileName}}: {{pad "|" ""}} -{{pad "|" .FilePos}} {{.Source}} +{{- range .Positions}} +{{- if .SkipLines}} +{{pad "|" ""}} {{"..."}} +{{- end}} +{{pad "|" .Pos}} {{.Source}} +{{- end}} {{pad "|" ""}} {{- end}} @@ -43,8 +48,8 @@ const schemaErrorReportTemplate = ` {{- range .Hints}} {{pad "=" ""}} hint: {{.}} {{- end}} -{{- end}} -{{.MiscErrorMessage}} +{{end}} +{{- .MiscErrorMessage}} ` func NewSchemaError(summary string, errs ...error) error { @@ -55,6 +60,7 @@ func NewSchemaError(summary string, errs ...error) error { failures = append(failures, assertionFailure{ Description: typeCheckAssertionErr.description, FileName: typeCheckAssertionErr.position.GetFile(), + Positions: createPosInfo(typeCheckAssertionErr.annPositions, typeCheckAssertionErr.position), FilePos: typeCheckAssertionErr.position.AsIntString(), FromMemory: typeCheckAssertionErr.position.FromMemory(), SourceName: "Data value calculated", @@ -75,7 +81,8 @@ func NewSchemaError(summary string, errs ...error) error { } } -func NewMismatchedTypeAssertionError(foundType yamlmeta.TypeWithValues, expectedType yamlmeta.Type) error { +// NewMismatchedTypeAssertionError generates an error given that `foundNode` is not of the `expectedType`. +func NewMismatchedTypeAssertionError(foundNode yamlmeta.Node, expectedType Type) error { var expectedTypeString string if expectedType.GetDefinitionPosition().IsKnown() { switch expectedType.(type) { @@ -87,19 +94,43 @@ func NewMismatchedTypeAssertionError(foundType yamlmeta.TypeWithValues, expected } return schemaAssertionError{ - position: foundType.GetPosition(), + position: foundNode.GetPosition(), expected: fmt.Sprintf("%s (by %s)", expectedTypeString, expectedType.GetDefinitionPosition().AsCompactString()), - found: foundType.ValueTypeAsString(), + found: nodeValueTypeAsString(foundNode), } } -func NewUnexpectedKeyAssertionError(found *yamlmeta.MapItem, definition *filepos.Position) error { - return schemaAssertionError{ - position: found.GetPosition(), - expected: fmt.Sprintf("(a key defined in map) (by %s)", definition.AsCompactString()), - found: fmt.Sprintf("%v", found.Key), - hints: []string{"declare data values in schema and override them in a data values document"}, +func nodeValueTypeAsString(n yamlmeta.Node) string { + switch typed := n.(type) { + case *yamlmeta.DocumentSet, *yamlmeta.Map, *yamlmeta.Array: + return yamlmeta.TypeName(typed) + default: + return yamlmeta.TypeName(typed.GetValues()[0]) + } +} + +// NewUnexpectedKeyAssertionError generates a schema assertion error including the context (and hints) needed to report it to the user +func NewUnexpectedKeyAssertionError(found *yamlmeta.MapItem, definition *filepos.Position, allowedKeys []string) error { + key := fmt.Sprintf("%v", found.Key) + err := schemaAssertionError{ + description: "Given data value is not declared in schema", + position: found.GetPosition(), + found: key, } + sort.Strings(allowedKeys) + switch numKeys := len(allowedKeys); { + case numKeys == 1: + err.expected = fmt.Sprintf(`a %s with the key named "%s" (from %s)`, yamlmeta.TypeName(found), allowedKeys[0], definition.AsCompactString()) + case numKeys > 1 && numKeys <= 9: // Miller's Law + err.expected = fmt.Sprintf("one of { %s } (from %s)", strings.Join(allowedKeys, ", "), definition.AsCompactString()) + default: + err.expected = fmt.Sprintf("a key declared in map (from %s)", definition.AsCompactString()) + } + mostSimilarKey := spell.Nearest(key, allowedKeys) + if mostSimilarKey != "" { + err.hints = append(err.hints, fmt.Sprintf(`did you mean "%s"?`, mostSimilarKey)) + } + return err } type schemaError struct { @@ -111,6 +142,7 @@ type schemaError struct { type assertionFailure struct { Description string FileName string + Positions []posInfo Source string FilePos string FromMemory bool @@ -122,11 +154,41 @@ type assertionFailure struct { type schemaAssertionError struct { error - position *filepos.Position - description string - expected string - found string - hints []string + annPositions []*filepos.Position + position *filepos.Position + description string + expected string + found string + hints []string +} + +type posInfo struct { + Pos string + Source string + SkipLines bool +} + +func createPosInfo(annPosList []*filepos.Position, nodePos *filepos.Position) []posInfo { + sort.SliceStable(annPosList, func(i, j int) bool { + if !annPosList[i].IsKnown() { + return true + } + if !annPosList[j].IsKnown() { + return false + } + return annPosList[i].LineNum() < annPosList[j].LineNum() + }) + + allPositions := append(annPosList, nodePos) + var positionsInfo []posInfo + for i, p := range allPositions { + skipLines := false + if i > 0 { + skipLines = !p.IsNextTo(allPositions[i-1]) + } + positionsInfo = append(positionsInfo, posInfo{Pos: p.AsIntString(), Source: p.GetLine(), SkipLines: skipLines}) + } + return positionsInfo } func (e schemaError) Error() string { diff --git a/vendor/carvel.dev/ytt/pkg/schema/openapi.go b/vendor/carvel.dev/ytt/pkg/schema/openapi.go new file mode 100644 index 000000000..e92cb0711 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/openapi.go @@ -0,0 +1,267 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + "sort" + + "carvel.dev/ytt/pkg/yamlmeta" +) + +// keys used when generating an OpenAPI Document +const ( + titleProp = "title" + typeProp = "type" + additionalPropsProp = "additionalProperties" + formatProp = "format" + nullableProp = "nullable" + deprecatedProp = "deprecated" + descriptionProp = "description" + exampleDescriptionProp = "x-example-description" + exampleProp = "example" + itemsProp = "items" + propertiesProp = "properties" + defaultProp = "default" + minProp = "minimum" + maxProp = "maximum" + minLenProp = "minLength" // for strings + maxLenProp = "maxLength" + minItemsProp = "minItems" // for arrays + maxItemsProp = "maxItems" + minPropertiesProp = "minProperties" // for objects + maxPropertiesProp = "maxProperties" + enumProp = "enum" +) + +var propOrder = map[string]int{ + titleProp: 0, + typeProp: 1, + additionalPropsProp: 2, + formatProp: 3, + nullableProp: 4, + deprecatedProp: 5, + descriptionProp: 6, + exampleDescriptionProp: 7, + exampleProp: 8, + itemsProp: 9, + propertiesProp: 10, + defaultProp: 11, + minProp: 12, + maxProp: 13, + minLenProp: 14, + maxLenProp: 15, + minItemsProp: 16, + maxItemsProp: 17, + minPropertiesProp: 18, + maxPropertiesProp: 19, + enumProp: 20, +} + +type openAPIKeys []*yamlmeta.MapItem + +func (o openAPIKeys) Len() int { return len(o) } +func (o openAPIKeys) Less(i, j int) bool { + return propOrder[o[i].Key.(string)] < propOrder[o[j].Key.(string)] +} +func (o openAPIKeys) Swap(i, j int) { o[i], o[j] = o[j], o[i] } + +// OpenAPIDocument holds the document type used for creating an OpenAPI document +type OpenAPIDocument struct { + docType *DocumentType +} + +// NewOpenAPIDocument creates an instance of an OpenAPIDocument based on the given DocumentType +func NewOpenAPIDocument(docType *DocumentType) *OpenAPIDocument { + return &OpenAPIDocument{docType} +} + +// AsDocument generates a new AST of this OpenAPI v3.0.x document, populating the `schemas:` section with the +// type information contained in `docType`. +func (o *OpenAPIDocument) AsDocument() *yamlmeta.Document { + openAPIProperties := o.calculateProperties(o.docType) + + return &yamlmeta.Document{Value: &yamlmeta.Map{Items: []*yamlmeta.MapItem{ + {Key: "openapi", Value: "3.0.0"}, + {Key: "info", Value: &yamlmeta.Map{Items: []*yamlmeta.MapItem{ + {Key: "version", Value: "0.1.0"}, + {Key: titleProp, Value: "Schema for data values, generated by ytt"}, + }}}, + {Key: "paths", Value: &yamlmeta.Map{}}, + {Key: "components", Value: &yamlmeta.Map{Items: []*yamlmeta.MapItem{ + {Key: "schemas", Value: &yamlmeta.Map{Items: []*yamlmeta.MapItem{ + {Key: "dataValues", Value: openAPIProperties}, + }}}, + }}}, + }}} +} + +func (o *OpenAPIDocument) calculateProperties(schemaVal interface{}) *yamlmeta.Map { + switch typedValue := schemaVal.(type) { + case *DocumentType: + result := o.calculateProperties(typedValue.GetValueType()) + result.Items = append(result.Items, o.convertValidations(typedValue)...) + sort.Sort(openAPIKeys(result.Items)) + return result + + case *MapType: + var items openAPIKeys + items = append(items, o.collectDocumentation(typedValue)...) + items = append(items, o.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: typeProp, Value: "object"}) + items = append(items, &yamlmeta.MapItem{Key: additionalPropsProp, Value: false}) + + var properties []*yamlmeta.MapItem + for _, i := range typedValue.Items { + mi := yamlmeta.MapItem{Key: i.Key, Value: o.calculateProperties(i)} + properties = append(properties, &mi) + } + items = append(items, &yamlmeta.MapItem{Key: propertiesProp, Value: &yamlmeta.Map{Items: properties}}) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *MapItemType: + result := o.calculateProperties(typedValue.GetValueType()) + result.Items = append(result.Items, o.convertValidations(typedValue)...) + sort.Sort(openAPIKeys(result.Items)) + return result + + case *ArrayType: + var items openAPIKeys + items = append(items, o.collectDocumentation(typedValue)...) + items = append(items, o.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: typeProp, Value: "array"}) + items = append(items, &yamlmeta.MapItem{Key: defaultProp, Value: typedValue.GetDefaultValue()}) + + valueType := typedValue.GetValueType().(*ArrayItemType) + properties := o.calculateProperties(valueType.GetValueType()) + items = append(items, &yamlmeta.MapItem{Key: itemsProp, Value: properties}) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *ScalarType: + var items openAPIKeys + items = append(items, o.collectDocumentation(typedValue)...) + items = append(items, o.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: defaultProp, Value: typedValue.GetDefaultValue()}) + + typeString := o.openAPITypeFor(typedValue) + items = append(items, &yamlmeta.MapItem{Key: typeProp, Value: typeString}) + + if typedValue.String() == "float" { + items = append(items, &yamlmeta.MapItem{Key: formatProp, Value: "float"}) + } + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *NullType: + var items openAPIKeys + items = append(items, o.collectDocumentation(typedValue)...) + items = append(items, o.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: nullableProp, Value: true}) + + properties := o.calculateProperties(typedValue.GetValueType()) + items = append(items, properties.Items...) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *AnyType: + var items openAPIKeys + items = append(items, o.collectDocumentation(typedValue)...) + items = append(items, o.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: nullableProp, Value: true}) + items = append(items, &yamlmeta.MapItem{Key: defaultProp, Value: typedValue.GetDefaultValue()}) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + default: + panic(fmt.Sprintf("Unrecognized type %T", schemaVal)) + } +} + +func (*OpenAPIDocument) collectDocumentation(typedValue Type) []*yamlmeta.MapItem { + var items []*yamlmeta.MapItem + if typedValue.GetTitle() != "" { + items = append(items, &yamlmeta.MapItem{Key: titleProp, Value: typedValue.GetTitle()}) + } + if typedValue.GetDescription() != "" { + items = append(items, &yamlmeta.MapItem{Key: descriptionProp, Value: typedValue.GetDescription()}) + } + if isDeprecated, _ := typedValue.IsDeprecated(); isDeprecated { + items = append(items, &yamlmeta.MapItem{Key: deprecatedProp, Value: isDeprecated}) + } + examples := typedValue.GetExamples() + if len(examples) != 0 { + items = append(items, &yamlmeta.MapItem{Key: exampleDescriptionProp, Value: examples[0].description}) + items = append(items, &yamlmeta.MapItem{Key: exampleProp, Value: examples[0].example}) + } + return items +} + +// convertValidations converts the starlark validation map to a list of OpenAPI properties +func (*OpenAPIDocument) convertValidations(schemaVal Type) []*yamlmeta.MapItem { + validation := schemaVal.GetValidation() + if validation == nil { + return nil + } + + var items []*yamlmeta.MapItem + + if value, found := validation.HasSimpleMinLength(); found { + containedValue := schemaVal.GetValueType() + switch containedValue.(type) { + case *ArrayType: + items = append(items, &yamlmeta.MapItem{Key: minItemsProp, Value: value}) + case *MapType: + items = append(items, &yamlmeta.MapItem{Key: minPropertiesProp, Value: value}) + default: + if containedValue.String() == "string" { + items = append(items, &yamlmeta.MapItem{Key: minLenProp, Value: value}) + } + } + } + if value, found := validation.HasSimpleMaxLength(); found { + containedValue := schemaVal.GetValueType() + switch containedValue.(type) { + case *ArrayType: + items = append(items, &yamlmeta.MapItem{Key: maxItemsProp, Value: value}) + case *MapType: + items = append(items, &yamlmeta.MapItem{Key: maxPropertiesProp, Value: value}) + default: + if containedValue.String() == "string" { + items = append(items, &yamlmeta.MapItem{Key: maxLenProp, Value: value}) + } + } + } + if value, found := validation.HasSimpleMin(); found { + items = append(items, &yamlmeta.MapItem{Key: minProp, Value: value}) + } + if value, found := validation.HasSimpleMax(); found { + items = append(items, &yamlmeta.MapItem{Key: maxProp, Value: value}) + } + if value, found := validation.HasSimpleOneOf(); found { + items = append(items, &yamlmeta.MapItem{Key: enumProp, Value: value}) + } + return items +} + +func (*OpenAPIDocument) openAPITypeFor(astType *ScalarType) string { + switch astType.ValueType { + case StringType: + return "string" + case FloatType: + return "number" + case IntType: + return "integer" + case BoolType: + return "boolean" + default: + panic(fmt.Sprintf("Unrecognized type: %T", astType.ValueType)) + } +} diff --git a/vendor/carvel.dev/ytt/pkg/schema/schema.go b/vendor/carvel.dev/ytt/pkg/schema/schema.go new file mode 100644 index 000000000..317a3d1a1 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/schema.go @@ -0,0 +1,264 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/validations" + "carvel.dev/ytt/pkg/yamlmeta" +) + +// NewDocumentType constructs a complete DocumentType based on the contents of a schema YAML document. +func NewDocumentType(doc *yamlmeta.Document) (*DocumentType, error) { + typeOfValue, err := getType(doc) + if err != nil { + return nil, err + } + + defaultValue, err := getValue(doc, typeOfValue) + if err != nil { + return nil, err + } + + v, err := getValidation(doc) + if err != nil { + return nil, err + } + + typeOfValue.SetDefaultValue(defaultValue) + + return &DocumentType{Source: doc, Position: doc.Position, ValueType: typeOfValue, defaultValue: defaultValue, validations: v}, nil +} + +func NewMapType(m *yamlmeta.Map) (*MapType, error) { + mapType := &MapType{Position: m.Position} + + for _, mapItem := range m.Items { + mapItemType, err := NewMapItemType(mapItem) + if err != nil { + return nil, err + } + mapType.Items = append(mapType.Items, mapItemType) + } + + return mapType, nil +} + +func NewMapItemType(item *yamlmeta.MapItem) (*MapItemType, error) { + typeOfValue, err := getType(item) + if err != nil { + return nil, err + } + + defaultValue, err := getValue(item, typeOfValue) + if err != nil { + return nil, err + } + + v, err := getValidation(item) + if err != nil { + return nil, err + } + + typeOfValue.SetDefaultValue(defaultValue) + + return &MapItemType{Key: item.Key, ValueType: typeOfValue, defaultValue: defaultValue, Position: item.Position, validations: v}, nil +} + +func NewArrayType(a *yamlmeta.Array) (*ArrayType, error) { + if len(a.Items) != 1 { + return nil, NewSchemaError("Invalid schema - wrong number of items in array definition", schemaAssertionError{ + position: a.Position, + expected: "exactly 1 array item, of the desired type", + found: fmt.Sprintf("%d array items", len(a.Items)), + hints: []string{"in schema, the one item of the array implies the type of its elements.", "in schema, the default value for an array is always an empty list.", "default values can be overridden via a data values overlay."}, + }) + } + + arrayItemType, err := NewArrayItemType(a.Items[0]) + + if err != nil { + return nil, err + } + + return &ArrayType{ItemsType: arrayItemType, defaultValue: &yamlmeta.Array{}, Position: a.Position}, nil +} + +func NewArrayItemType(item *yamlmeta.ArrayItem) (*ArrayItemType, error) { + typeOfValue, err := getType(item) + if err != nil { + return nil, err + } + + defaultValue, err := getValue(item, typeOfValue) + if err != nil { + return nil, err + } + + v, err := getValidation(item) + if err != nil { + return nil, err + } + + typeOfValue.SetDefaultValue(defaultValue) + + return &ArrayItemType{ValueType: typeOfValue, defaultValue: defaultValue, Position: item.GetPosition(), validations: v}, nil +} + +func getType(node yamlmeta.Node) (Type, error) { + var typeOfValue Type + + anns, err := collectTypeAnnotations(node) + if err != nil { + return nil, NewSchemaError("Invalid schema", err) + } + typeOfValue, err = getTypeFromAnnotations(anns) + if err != nil { + return nil, NewSchemaError("Invalid schema", err) + } + + if typeOfValue == nil { + typeOfValue, err = InferTypeFromValue(node.GetValues()[0], node.GetPosition()) + if err != nil { + return nil, err + } + } + err = valueTypeAllowsItemValue(typeOfValue, node.GetValues()[0], node.GetPosition()) + if err != nil { + return nil, err + } + + docAnns, err := collectDocumentationAnnotations(node) + if err != nil { + return nil, NewSchemaError("Invalid schema", err) + } + err = setDocumentationFromAnns(docAnns, typeOfValue) + if err != nil { + return nil, err + } + + return typeOfValue, nil +} + +func getValue(node yamlmeta.Node, t Type) (interface{}, error) { + anns, err := collectValueAnnotations(node, t) + if err != nil { + return nil, NewSchemaError("Invalid schema", err) + } + + for _, ann := range anns { + if defaultAnn, ok := ann.(*DefaultAnnotation); ok { + return getValueFromAnn(defaultAnn, t) + } + } + + return t.GetDefaultValue(), nil +} + +func getValidation(node yamlmeta.Node) (*validations.NodeValidation, error) { + validationAnn, err := processValidationAnnotation(node) + if err != nil { + return nil, err + } + + if validationAnn != nil { + return validationAnn.GetValidation(), nil + } + return nil, nil +} + +// getValueFromAnn extracts the value from the annotation and validates its type +func getValueFromAnn(defaultAnn *DefaultAnnotation, t Type) (interface{}, error) { + var typeCheck TypeCheck + + defaultValue := defaultAnn.Val() + if node, ok := defaultValue.(yamlmeta.Node); ok { + defaultNode := node.DeepCopyAsNode() + typeCheck = t.AssignTypeTo(defaultNode) + if !typeCheck.HasViolations() { + typeCheck = CheckNode(defaultNode) + } + defaultValue = defaultNode + } else { + typeCheck = t.CheckType(&yamlmeta.MapItem{Value: defaultValue, Position: t.GetDefinitionPosition()}) + } + if typeCheck.HasViolations() { + var violations []error + // add violating annotation position to error + for _, err := range typeCheck.Violations { + if typeCheckAssertionErr, ok := err.(schemaAssertionError); ok { + typeCheckAssertionErr.annPositions = []*filepos.Position{defaultAnn.GetPosition()} + typeCheckAssertionErr.found = typeCheckAssertionErr.found + fmt.Sprintf(" (at %v)", defaultAnn.GetPosition().AsCompactString()) + violations = append(violations, typeCheckAssertionErr) + } else { + violations = append(violations, err) + } + } + return nil, NewSchemaError(fmt.Sprintf("Invalid schema - @%v is wrong type", AnnotationDefault), violations...) + } + + return defaultValue, nil +} + +// InferTypeFromValue detects and constructs an instance of the Type of `value`. +func InferTypeFromValue(value interface{}, position *filepos.Position) (Type, error) { + switch typedContent := value.(type) { + case *yamlmeta.Document: + docType, err := NewDocumentType(typedContent) + if err != nil { + return nil, err + } + return docType, nil + case *yamlmeta.Map: + mapType, err := NewMapType(typedContent) + if err != nil { + return nil, err + } + return mapType, nil + case *yamlmeta.Array: + arrayType, err := NewArrayType(typedContent) + if err != nil { + return nil, err + } + return arrayType, nil + case string: + return &ScalarType{ValueType: StringType, defaultValue: typedContent, Position: position}, nil + case float64: + return &ScalarType{ValueType: FloatType, defaultValue: typedContent, Position: position}, nil + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + return &ScalarType{ValueType: IntType, defaultValue: typedContent, Position: position}, nil + case bool: + return &ScalarType{ValueType: BoolType, defaultValue: typedContent, Position: position}, nil + case nil: + return nil, nil + default: + return nil, fmt.Errorf("Expected value '%s' to be a map, array, or scalar, but was %s", value, yamlmeta.TypeName(typedContent)) + } +} + +func valueTypeAllowsItemValue(explicitType Type, itemValue interface{}, position *filepos.Position) error { + switch explicitType.(type) { + case *AnyType: + if node, ok := itemValue.(yamlmeta.Node); ok { + // search children for annotations + err := yamlmeta.Walk(node, checkForAnnotations{}) + if err != nil { + return err + } + } + return nil + default: + if itemValue == nil { + return NewSchemaError("Invalid schema - null value not allowed here", schemaAssertionError{ + position: position, + expected: "non-null value", + found: "null value", + hints: []string{"in YAML, omitting a value implies null.", "to set the default value to null, annotate with @schema/nullable.", "to allow any value, annotate with @schema/type any=True."}, + }) + } + } + return nil +} diff --git a/vendor/carvel.dev/ytt/pkg/schema/type.go b/vendor/carvel.dev/ytt/pkg/schema/type.go new file mode 100644 index 000000000..4ef273cf7 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/type.go @@ -0,0 +1,657 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/validations" + "carvel.dev/ytt/pkg/yamlmeta" +) + +// Type encapsulates a schema that describes a yamlmeta.Node. +type Type interface { + AssignTypeTo(node yamlmeta.Node) TypeCheck + CheckType(node yamlmeta.Node) TypeCheck + + GetValueType() Type + GetDefaultValue() interface{} + SetDefaultValue(interface{}) + GetDefinitionPosition() *filepos.Position + + GetDescription() string + SetDescription(string) + GetTitle() string + SetTitle(string) + GetExamples() []Example + SetExamples([]Example) + IsDeprecated() (bool, string) + SetDeprecated(bool, string) + GetValidation() *validations.NodeValidation + String() string +} + +var _ Type = (*DocumentType)(nil) +var _ Type = (*MapType)(nil) +var _ Type = (*MapItemType)(nil) +var _ Type = (*ArrayType)(nil) +var _ Type = (*ArrayItemType)(nil) +var _ Type = (*ScalarType)(nil) +var _ Type = (*AnyType)(nil) +var _ Type = (*NullType)(nil) + +type DocumentType struct { + Source *yamlmeta.Document + ValueType Type // typically one of: MapType, ArrayType, ScalarType + Position *filepos.Position + defaultValue interface{} + validations *validations.NodeValidation +} + +type MapType struct { + Items []*MapItemType + Position *filepos.Position + documentation documentation +} + +type MapItemType struct { + Key interface{} // usually a string + ValueType Type + Position *filepos.Position + defaultValue interface{} + validations *validations.NodeValidation +} + +type ArrayType struct { + ItemsType Type + Position *filepos.Position + defaultValue interface{} + documentation documentation +} + +type ArrayItemType struct { + ValueType Type + Position *filepos.Position + defaultValue interface{} + validations *validations.NodeValidation +} + +type ScalarType struct { + ValueType interface{} + Position *filepos.Position + defaultValue interface{} + documentation documentation +} + +type AnyType struct { + defaultValue interface{} + Position *filepos.Position + documentation documentation +} + +type NullType struct { + ValueType Type + Position *filepos.Position + documentation documentation +} + +// The total set of supported scalars. +const ( + FloatType = float64(0) + StringType = "" + IntType = int64(0) + BoolType = false +) + +// GetValueType provides the type of the value +func (t *DocumentType) GetValueType() Type { + return t.ValueType +} + +// GetValueType provides the type of the value +func (m MapType) GetValueType() Type { + panic("Not implemented because it is unreachable") +} + +// GetValueType provides the type of the value +func (t MapItemType) GetValueType() Type { + return t.ValueType +} + +// GetValueType provides the type of the value +func (a ArrayType) GetValueType() Type { + return a.ItemsType +} + +// GetValueType provides the type of the value +func (a ArrayItemType) GetValueType() Type { + return a.ValueType +} + +// GetValueType provides the type of the value +func (s ScalarType) GetValueType() Type { + panic("Not implemented because it is unreachable") +} + +// GetValueType provides the type of the value +func (a AnyType) GetValueType() Type { + return &a +} + +// GetValueType provides the type of the value +func (n NullType) GetValueType() Type { + return n.ValueType +} + +// GetDefaultValue provides the default value +func (t DocumentType) GetDefaultValue() interface{} { + return &yamlmeta.Document{Value: t.defaultValue, Position: t.Position} +} + +// GetDefaultValue provides the default value +func (m MapType) GetDefaultValue() interface{} { + defaultValues := &yamlmeta.Map{Position: m.Position} + for _, item := range m.Items { + newItem := item.GetDefaultValue() + defaultValues.Items = append(defaultValues.Items, newItem.(*yamlmeta.MapItem)) + } + return defaultValues +} + +// GetDefaultValue provides the default value +func (t MapItemType) GetDefaultValue() interface{} { + return &yamlmeta.MapItem{Key: t.Key, Value: t.defaultValue, Position: t.Position} +} + +// GetDefaultValue provides the default value +func (a ArrayType) GetDefaultValue() interface{} { + return a.defaultValue +} + +// GetDefaultValue provides the default value +func (a ArrayItemType) GetDefaultValue() interface{} { + panic(fmt.Sprintf("Unexpected call to GetDefaultValue() on %+v", a)) +} + +// GetDefaultValue provides the default value +func (s ScalarType) GetDefaultValue() interface{} { + return s.defaultValue // scalar values are copied (even through an interface{} reference) +} + +// GetDefaultValue provides the default value +func (a AnyType) GetDefaultValue() interface{} { + if node, ok := a.defaultValue.(yamlmeta.Node); ok { + return node.DeepCopyAsInterface() + } + return a.defaultValue +} + +// GetDefaultValue provides the default value +func (n NullType) GetDefaultValue() interface{} { + return nil +} + +// SetDefaultValue sets the default value of the entire document to `val` +func (t *DocumentType) SetDefaultValue(val interface{}) { + t.defaultValue = val +} + +// SetDefaultValue is ignored as default values should be set on each MapItemType, individually. +func (m *MapType) SetDefaultValue(_ interface{}) { + // TODO: determine if we should set the contents of a MapType by setting the given Map...? + return +} + +// SetDefaultValue sets the default value to `val` +func (t *MapItemType) SetDefaultValue(val interface{}) { + t.defaultValue = val +} + +// SetDefaultValue sets the default value to `val` +func (a *ArrayType) SetDefaultValue(val interface{}) { + a.defaultValue = val +} + +// SetDefaultValue sets the default value to `val` +func (a *ArrayItemType) SetDefaultValue(val interface{}) { + a.defaultValue = val +} + +// SetDefaultValue sets the default value to `val` +func (s *ScalarType) SetDefaultValue(val interface{}) { + s.defaultValue = val +} + +// SetDefaultValue does nothing +func (a *AnyType) SetDefaultValue(val interface{}) { + a.defaultValue = val +} + +// SetDefaultValue sets the default value of the wrapped type to `val` +func (n *NullType) SetDefaultValue(val interface{}) { + n.GetValueType().SetDefaultValue(val) +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (t *DocumentType) GetDefinitionPosition() *filepos.Position { + return t.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (m MapType) GetDefinitionPosition() *filepos.Position { + return m.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (t MapItemType) GetDefinitionPosition() *filepos.Position { + return t.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (a ArrayType) GetDefinitionPosition() *filepos.Position { + return a.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (a ArrayItemType) GetDefinitionPosition() *filepos.Position { + return a.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (s ScalarType) GetDefinitionPosition() *filepos.Position { + return s.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (a AnyType) GetDefinitionPosition() *filepos.Position { + return a.Position +} + +// GetDefinitionPosition reports the location in source schema that contains this type definition. +func (n NullType) GetDefinitionPosition() *filepos.Position { + return n.Position +} + +// GetDescription provides descriptive information +func (t *DocumentType) GetDescription() string { + return "" +} + +// GetDescription provides descriptive information +func (m *MapType) GetDescription() string { + return m.documentation.description +} + +// GetDescription provides descriptive information +func (t *MapItemType) GetDescription() string { + return "" +} + +// GetDescription provides descriptive information +func (a *ArrayType) GetDescription() string { + return a.documentation.description +} + +// GetDescription provides descriptive information +func (a *ArrayItemType) GetDescription() string { + return "" +} + +// GetDescription provides descriptive information +func (s *ScalarType) GetDescription() string { + return s.documentation.description +} + +// GetDescription provides descriptive information +func (a *AnyType) GetDescription() string { + return a.documentation.description +} + +// GetDescription provides descriptive information +func (n *NullType) GetDescription() string { + return n.documentation.description +} + +// SetDescription sets the description of the type +func (t *DocumentType) SetDescription(_ string) {} + +// SetDescription sets the description of the type +func (m *MapType) SetDescription(desc string) { + m.documentation.description = desc +} + +// SetDescription sets the description of the type +func (t *MapItemType) SetDescription(_ string) {} + +// SetDescription sets the description of the type +func (a *ArrayType) SetDescription(desc string) { + a.documentation.description = desc +} + +// SetDescription sets the description of the type +func (a *ArrayItemType) SetDescription(_ string) {} + +// SetDescription sets the description of the type +func (s *ScalarType) SetDescription(desc string) { + s.documentation.description = desc +} + +// SetDescription sets the description of the type +func (a *AnyType) SetDescription(desc string) { + a.documentation.description = desc +} + +// SetDescription sets the description of the type +func (n *NullType) SetDescription(desc string) { + n.documentation.description = desc +} + +// GetTitle provides title information +func (t *DocumentType) GetTitle() string { + return "" +} + +// GetTitle provides title information +func (m *MapType) GetTitle() string { + return m.documentation.title +} + +// GetTitle provides title information +func (t *MapItemType) GetTitle() string { + return "" +} + +// GetTitle provides title information +func (a *ArrayType) GetTitle() string { + return a.documentation.title +} + +// GetTitle provides title information +func (a *ArrayItemType) GetTitle() string { + return "" +} + +// GetTitle provides title information +func (s *ScalarType) GetTitle() string { + return s.documentation.title +} + +// GetTitle provides title information +func (a *AnyType) GetTitle() string { + return a.documentation.title +} + +// GetTitle provides title information +func (n *NullType) GetTitle() string { + return n.documentation.title +} + +// SetTitle sets the title of the type +func (t *DocumentType) SetTitle(_ string) {} + +// SetTitle sets the title of the type +func (m *MapType) SetTitle(title string) { + m.documentation.title = title +} + +// SetTitle sets the title of the type +func (t *MapItemType) SetTitle(_ string) {} + +// SetTitle sets the title of the type +func (a *ArrayType) SetTitle(title string) { + a.documentation.title = title +} + +// SetTitle sets the title of the type +func (a *ArrayItemType) SetTitle(_ string) {} + +// SetTitle sets the title of the type +func (s *ScalarType) SetTitle(title string) { + s.documentation.title = title +} + +// SetTitle sets the title of the type +func (a *AnyType) SetTitle(title string) { + a.documentation.title = title +} + +// SetTitle sets the title of the type +func (n *NullType) SetTitle(title string) { + n.documentation.title = title +} + +// GetExamples provides descriptive example information +func (t *DocumentType) GetExamples() []Example { + return nil +} + +// GetExamples provides descriptive example information +func (m *MapType) GetExamples() []Example { + return m.documentation.examples +} + +// GetExamples provides descriptive example information +func (t *MapItemType) GetExamples() []Example { + return nil +} + +// GetExamples provides descriptive example information +func (a *ArrayType) GetExamples() []Example { + return a.documentation.examples +} + +// GetExamples provides descriptive example information +func (a *ArrayItemType) GetExamples() []Example { + return nil +} + +// GetExamples provides descriptive example information +func (s *ScalarType) GetExamples() []Example { + return s.documentation.examples +} + +// GetExamples provides descriptive example information +func (a *AnyType) GetExamples() []Example { + return a.documentation.examples +} + +// GetExamples provides descriptive example information +func (n *NullType) GetExamples() []Example { + return n.documentation.examples +} + +// SetExamples sets the description and example of the type +func (t *DocumentType) SetExamples(_ []Example) {} + +// SetExamples sets the description and example of the type +func (m *MapType) SetExamples(exs []Example) { + m.documentation.examples = exs +} + +// SetExamples sets the description and example of the type +func (t *MapItemType) SetExamples(_ []Example) {} + +// SetExamples sets the description and example of the type +func (a *ArrayType) SetExamples(exs []Example) { + a.documentation.examples = exs +} + +// SetExamples sets the description and example of the type +func (a *ArrayItemType) SetExamples(_ []Example) {} + +// SetExamples sets the description and example of the type +func (s *ScalarType) SetExamples(exs []Example) { + s.documentation.examples = exs +} + +// SetExamples sets the description and example of the type +func (a *AnyType) SetExamples(exs []Example) { + a.documentation.examples = exs +} + +// SetExamples sets the description and example of the type +func (n *NullType) SetExamples(exs []Example) { + n.documentation.examples = exs +} + +// IsDeprecated provides deprecated field information +func (t *DocumentType) IsDeprecated() (bool, string) { + return false, "" +} + +// IsDeprecated provides deprecated field information +func (m *MapType) IsDeprecated() (bool, string) { + return m.documentation.deprecated, m.documentation.deprecationNotice + +} + +// IsDeprecated provides deprecated field information +func (t *MapItemType) IsDeprecated() (bool, string) { + return false, "" +} + +// IsDeprecated provides deprecated field information +func (a *ArrayType) IsDeprecated() (bool, string) { + return a.documentation.deprecated, a.documentation.deprecationNotice +} + +// IsDeprecated provides deprecated field information +func (a *ArrayItemType) IsDeprecated() (bool, string) { + return false, "" +} + +// IsDeprecated provides deprecated field information +func (s *ScalarType) IsDeprecated() (bool, string) { + return s.documentation.deprecated, s.documentation.deprecationNotice +} + +// IsDeprecated provides deprecated field information +func (a *AnyType) IsDeprecated() (bool, string) { + return a.documentation.deprecated, a.documentation.deprecationNotice +} + +// IsDeprecated provides deprecated field information +func (n *NullType) IsDeprecated() (bool, string) { + return n.documentation.deprecated, n.documentation.deprecationNotice +} + +// SetDeprecated sets the deprecated field value +func (t *DocumentType) SetDeprecated(_ bool, _ string) {} + +// SetDeprecated sets the deprecated field value +func (m *MapType) SetDeprecated(deprecated bool, notice string) { + m.documentation.deprecationNotice = notice + m.documentation.deprecated = deprecated +} + +// SetDeprecated sets the deprecated field value +func (t *MapItemType) SetDeprecated(_ bool, _ string) {} + +// SetDeprecated sets the deprecated field value +func (a *ArrayType) SetDeprecated(deprecated bool, notice string) { + a.documentation.deprecationNotice = notice + a.documentation.deprecated = deprecated +} + +// SetDeprecated sets the deprecated field value +func (a *ArrayItemType) SetDeprecated(_ bool, _ string) {} + +// SetDeprecated sets the deprecated field value +func (s *ScalarType) SetDeprecated(deprecated bool, notice string) { + s.documentation.deprecationNotice = notice + s.documentation.deprecated = deprecated +} + +// SetDeprecated sets the deprecated field value +func (a *AnyType) SetDeprecated(deprecated bool, notice string) { + a.documentation.deprecationNotice = notice + a.documentation.deprecated = deprecated +} + +// SetDeprecated sets the deprecated field value +func (n *NullType) SetDeprecated(deprecated bool, notice string) { + n.documentation.deprecationNotice = notice + n.documentation.deprecated = deprecated +} + +// GetValidation provides the validation from @schema/validation for a node +func (t *DocumentType) GetValidation() *validations.NodeValidation { + return t.validations +} + +// GetValidation provides the validation from @schema/validation for a node +func (m *MapType) GetValidation() *validations.NodeValidation { + return nil +} + +// GetValidation provides the validation from @schema/validation for a node +func (t *MapItemType) GetValidation() *validations.NodeValidation { + return t.validations +} + +// GetValidation provides the validation from @schema/validation for a node +func (a *ArrayType) GetValidation() *validations.NodeValidation { + return nil +} + +// GetValidation provides the validation from @schema/validation for a node +func (a *ArrayItemType) GetValidation() *validations.NodeValidation { + return a.validations +} + +// GetValidation provides the validation from @schema/validation for a node +func (s *ScalarType) GetValidation() *validations.NodeValidation { + return nil +} + +// GetValidation provides the validation from @schema/validation for a node +func (a AnyType) GetValidation() *validations.NodeValidation { + return nil +} + +// GetValidation provides the validation from @schema/validation for a node +func (n NullType) GetValidation() *validations.NodeValidation { + return nil +} + +// String produces a user-friendly name of the expected type. +func (t *DocumentType) String() string { + return yamlmeta.TypeName(&yamlmeta.Document{}) +} + +// String produces a user-friendly name of the expected type. +func (m MapType) String() string { + return yamlmeta.TypeName(&yamlmeta.Map{}) +} + +// String produces a user-friendly name of the expected type. +func (t MapItemType) String() string { + return fmt.Sprintf("%s: %s", t.Key, t.ValueType.String()) +} + +// String produces a user-friendly name of the expected type. +func (a ArrayType) String() string { + return yamlmeta.TypeName(&yamlmeta.Array{}) +} + +// String produces a user-friendly name of the expected type. +func (a ArrayItemType) String() string { + return fmt.Sprintf("- %s", a.ValueType.String()) +} + +// String produces a user-friendly name of the expected type. +func (s ScalarType) String() string { + return yamlmeta.TypeName(s.ValueType) +} + +// String produces a user-friendly name of the expected type. +func (a AnyType) String() string { + return "any" +} + +// String produces a user-friendly name of the expected type. +func (n NullType) String() string { + return "null" +} diff --git a/vendor/carvel.dev/ytt/pkg/schema/yamlmeta.go b/vendor/carvel.dev/ytt/pkg/schema/yamlmeta.go new file mode 100644 index 000000000..3f01952c2 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/schema/yamlmeta.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import "carvel.dev/ytt/pkg/yamlmeta" + +const schemaType = "schema/type" + +// GetType retrieves schema metadata from `n`, set previously via SetType(). +func GetType(n yamlmeta.Node) Type { + t := n.GetMeta(schemaType) + if t == nil { + return nil + } + return t.(Type) +} + +// SetType attaches schema metadata to `n`, later retrieved via GetType(). +func SetType(n yamlmeta.Node, t Type) { + n.SetMeta(schemaType, t) +} diff --git a/vendor/carvel.dev/ytt/pkg/spell/doc.go b/vendor/carvel.dev/ytt/pkg/spell/doc.go new file mode 100644 index 000000000..0f8f45a25 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/spell/doc.go @@ -0,0 +1,10 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package spell provides the ability to suggest an exact spelling of a word. + +In the context ytt, this is useful for errors that involve misspelled +identifiers. +*/ +package spell diff --git a/vendor/carvel.dev/ytt/pkg/spell/spell.go b/vendor/carvel.dev/ytt/pkg/spell/spell.go new file mode 100644 index 000000000..356e13736 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/spell/spell.go @@ -0,0 +1,115 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +// (this source was copied from https://github.com/google/starlark-go/blob/b0039bd2cfe369fe8f2bdba0614bafd1f9402dbb/internal/spell/spell.go) + +package spell + +import ( + "strings" + "unicode" +) + +// Nearest returns the element of candidates +// nearest to x using the Levenshtein metric, +// or "" if none were promising. +func Nearest(x string, candidates []string) string { + // Ignore underscores and case when matching. + fold := func(s string) string { + return strings.Map(func(r rune) rune { + if r == '_' { + return -1 + } + return unicode.ToLower(r) + }, s) + } + + x = fold(x) + + var best string + bestD := (len(x) + 1) / 2 // allow up to 50% typos + for _, c := range candidates { + d := levenshtein(x, fold(c), bestD) + if d < bestD { + bestD = d + best = c + } + } + return best +} + +// levenshtein returns the non-negative Levenshtein edit distance +// between the byte strings x and y. +// +// If the computed distance exceeds max, +// the function may return early with an approximate value > max. +func levenshtein(x, y string, max int) int { + // This implementation is derived from one by Laurent Le Brun in + // Bazel that uses the single-row space efficiency trick + // described at bitbucket.org/clearer/iosifovich. + + // Let x be the shorter string. + if len(x) > len(y) { + x, y = y, x + } + + // Remove common prefix. + for i := 0; i < len(x); i++ { + if x[i] != y[i] { + x = x[i:] + y = y[i:] + break + } + } + if x == "" { + return len(y) + } + + if d := abs(len(x) - len(y)); d > max { + return d // excessive length divergence + } + + row := make([]int, len(y)+1) + for i := range row { + row[i] = i + } + + for i := 1; i <= len(x); i++ { + row[0] = i + best := i + prev := i - 1 + for j := 1; j <= len(y); j++ { + a := prev + b2i(x[i-1] != y[j-1]) // substitution + b := 1 + row[j-1] // deletion + c := 1 + row[j] // insertion + k := min(a, min(b, c)) + prev, row[j] = row[j], k + best = min(best, k) + } + if best > max { + return best + } + } + return row[len(y)] +} + +func b2i(b bool) int { + if b { + return 1 + } + return 0 +} + +func min(x, y int) int { + if x < y { + return x + } + return y +} + +func abs(x int) int { + if x >= 0 { + return x + } + return -x +} diff --git a/vendor/github.com/k14s/ytt/pkg/template/ancestors.go b/vendor/carvel.dev/ytt/pkg/template/ancestors.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/template/ancestors.go rename to vendor/carvel.dev/ytt/pkg/template/ancestors.go index 3965c65fa..f1ef47015 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/ancestors.go +++ b/vendor/carvel.dev/ytt/pkg/template/ancestors.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template diff --git a/vendor/github.com/k14s/ytt/pkg/template/annotations.go b/vendor/carvel.dev/ytt/pkg/template/annotations.go similarity index 83% rename from vendor/github.com/k14s/ytt/pkg/template/annotations.go rename to vendor/carvel.dev/ytt/pkg/template/annotations.go index 3a874455e..bac3b28c4 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/annotations.go +++ b/vendor/carvel.dev/ytt/pkg/template/annotations.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -6,20 +6,16 @@ package template import ( "strings" + "carvel.dev/ytt/pkg/filepos" "github.com/k14s/starlark-go/starlark" ) -const ( - AnnotationComment AnnotationName = "comment" - AnnotationCode AnnotationName = "template/code" - AnnotationValue AnnotationName = "template/value" -) - type NodeAnnotations map[AnnotationName]NodeAnnotation type NodeAnnotation struct { - Args starlark.Tuple - Kwargs []starlark.Tuple + Args starlark.Tuple + Kwargs []starlark.Tuple + Position *filepos.Position } func NewAnnotations(node EvaluationNode) NodeAnnotations { diff --git a/vendor/github.com/k14s/ytt/pkg/template/compiled_template.go b/vendor/carvel.dev/ytt/pkg/template/compiled_template.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/template/compiled_template.go rename to vendor/carvel.dev/ytt/pkg/template/compiled_template.go index 46676ce41..8f077cea2 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/compiled_template.go +++ b/vendor/carvel.dev/ytt/pkg/template/compiled_template.go @@ -1,17 +1,18 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template import ( "fmt" + "strings" + "unicode" + + "carvel.dev/ytt/pkg/filepos" + tplcore "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/resolve" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/syntax" - "github.com/k14s/ytt/pkg/filepos" - tplcore "github.com/k14s/ytt/pkg/template/core" - "strings" - "unicode" ) type EvaluationCtxDialectName string @@ -27,6 +28,8 @@ type CompiledTemplate struct { ctxs []*EvaluationCtx } +// NewCompiledTemplate creates a CompiledTemplate containing the generated code, +// InstructionSet, and Nodes needed to template the resulting document. func NewCompiledTemplate(name string, code []Line, instructions *InstructionSet, nodes *Nodes, evalDialects EvaluationCtxDialects) *CompiledTemplate { @@ -95,6 +98,8 @@ func (e *CompiledTemplate) DebugCodeAsString() string { return strings.Join(result, "\n") } +// Eval templates a document by executing the compiled code and instructions from a CompiledTemplate. +// `instructionBindings` maps the compiled code and instructions to functions defined on a CompiledTemplate. func (e *CompiledTemplate) Eval(thread *starlark.Thread, loader CompiledTemplateLoader) ( starlark.StringDict, interface{}, error) { diff --git a/vendor/github.com/k14s/ytt/pkg/template/compiled_template_error.go b/vendor/carvel.dev/ytt/pkg/template/compiled_template_error.go similarity index 66% rename from vendor/github.com/k14s/ytt/pkg/template/compiled_template_error.go rename to vendor/carvel.dev/ytt/pkg/template/compiled_template_error.go index 7d8b8df01..77127237c 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/compiled_template_error.go +++ b/vendor/carvel.dev/ytt/pkg/template/compiled_template_error.go @@ -1,16 +1,18 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template import ( "fmt" + "reflect" + "regexp" "strings" + "carvel.dev/ytt/pkg/filepos" "github.com/k14s/starlark-go/resolve" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/syntax" - "github.com/k14s/ytt/pkg/filepos" ) type CompiledTemplateMultiError struct { @@ -81,7 +83,7 @@ func (e CompiledTemplateMultiError) Error() string { } } - result = append(result, fmt.Sprintf("- %s%s", topicLine, e.hintMsg(topicLine))) + result = append(result, fmt.Sprintf("- %s%s", topicLine, e.hintMsg(err))) for _, pos := range err.Positions { // TODO do better @@ -121,7 +123,7 @@ func (e CompiledTemplateMultiError) Error() string { } if len(otherLines) > 0 { - result = append(result, []string{"", fmt.Sprintf(" reason:")}...) + result = append(result, []string{"", " reason:"}...) for _, line := range otherLines { result = append(result, fmt.Sprintf(" %s", line)) } @@ -147,6 +149,26 @@ func (e CompiledTemplateMultiError) buildEvalErr(err *starlark.EvalError) Compil return result } +type sourceCode interface { + CodeAtLine(pos *filepos.Position) *Line +} + +// unavailableSource is a stub for when the source code line for a filepos.Position cannot be found. +// This occurs when the position refers to a file that is not part of this Library: +// - a function from another Library (e.g. via library.get().export()) +// - Starlark sourced from within ytt (e.g. some out-of-the-box validation functions) +type unavailableSource struct { +} + +func (s unavailableSource) CodeAtLine(pos *filepos.Position) *Line { + return &Line{ + SourceLine: &SourceLine{ + Position: pos, + Content: "(unavailable)", + }, + } +} + func (e CompiledTemplateMultiError) buildPos(pos syntax.Position) CompiledTemplateErrorPosition { // TODO seems to be a bug in starlark where, for example, // "function call2 takes exactly 1 positional argument (0 given)" @@ -155,12 +177,16 @@ func (e CompiledTemplateMultiError) buildPos(pos syntax.Position) CompiledTempla return CompiledTemplateErrorPosition{} } - ct, err := e.loader.FindCompiledTemplate(pos.Filename()) - if err != nil { - panic(fmt.Errorf("Expected to find compiled template: %s", err)) + var sc sourceCode + sc = e.loader.FindCompiledTemplate(pos.Filename()) + if reflect.ValueOf(sc).IsNil() { + // TODO: find a way to register/locate such sources from within the current Library so that we _can_ include it. + sc = unavailableSource{} } - line := ct.CodeAtLine(filepos.NewPosition(int(pos.Line))) + p := filepos.NewPositionInFile(int(pos.Line), pos.Filename()) + + line := sc.CodeAtLine(p) if line == nil { panic(fmt.Errorf("Expected to find compiled template line %d", pos.Line)) } @@ -168,42 +194,68 @@ func (e CompiledTemplateMultiError) buildPos(pos syntax.Position) CompiledTempla return CompiledTemplateErrorPosition{ Filename: pos.Filename(), TemplateLine: line, - BeforeTemplateLine: e.findClosestLine(ct, int(pos.Line), -1), - AfterTemplateLine: e.findClosestLine(ct, int(pos.Line), 1), + BeforeTemplateLine: e.findClosestLine(sc, int(pos.Line), -1), + AfterTemplateLine: e.findClosestLine(sc, int(pos.Line), 1), } } -func (CompiledTemplateMultiError) findClosestLine(ct *CompiledTemplate, posLine int, lineInc int) *Line { +func (CompiledTemplateMultiError) findClosestLine(sc sourceCode, posLine int, lineInc int) *Line { for { posLine += lineInc if posLine < 1 { return nil } - line := ct.CodeAtLine(filepos.NewPosition(posLine)) + line := sc.CodeAtLine(filepos.NewPosition(posLine)) if line == nil || line.SourceLine != nil { return line } } } -func (CompiledTemplateMultiError) hintMsg(errMsg string) string { +func (CompiledTemplateMultiError) isOperatorPresent(err CompiledTemplateError, op string) bool { + for _, pos := range err.Positions { + codeLine := pos.TemplateLine.Instruction.code + if strings.Contains(codeLine, op) { + return true + } + } + return false +} + +func (e CompiledTemplateMultiError) hintMsg(err CompiledTemplateError) string { hintMsg := "" - switch errMsg { - case "undefined: true": + switch { + case err.Msg == "undefined: true": hintMsg = "use 'True' instead of 'true' for boolean assignment" - case "undefined: false": + case err.Msg == "undefined: false": hintMsg = "use 'False' instead of 'false' for boolean assignment" - case "got newline, want ':'": + case err.Msg == "got newline, want ':'": hintMsg = "missing colon at the end of 'if/for/def' statement?" - case "undefined: null": + case err.Msg == "undefined: null": hintMsg = "use 'None' instead of 'null' to indicate no value" - case "undefined: nil": + case err.Msg == "undefined: nil": hintMsg = "use 'None' instead of 'nil' to indicate no value" - case "undefined: none": + case err.Msg == "undefined: none": hintMsg = "use 'None' instead of 'none' to indicate no value" - case "unhandled index operation struct[string]": + case err.Msg == "unhandled index operation struct[string]": hintMsg = "use getattr(...) to access struct field programmatically" + case regexp.MustCompile(`^unknown binary op: .+ \| .+$`).MatchString(err.Msg): + hintMsg = "use 'or' instead of '|' for logical-or" + case regexp.MustCompile(`^unknown binary op: .+ & .+$`).MatchString(err.Msg): + hintMsg = "use 'and' instead of '&' for logical-and" + case err.Msg == "got '&', want primary expression": + isOpPresent := e.isOperatorPresent(err, "&&") + if isOpPresent { + hintMsg = "use 'and' instead of '&&' for logical-and" + break + } + case err.Msg == "got '|', want primary expression": + isOpPresent := e.isOperatorPresent(err, "||") + if isOpPresent { + hintMsg = "use 'or' instead of '||' for logical-or" + break + } } if len(hintMsg) > 0 { diff --git a/vendor/github.com/k14s/ytt/pkg/template/compiled_template_loader.go b/vendor/carvel.dev/ytt/pkg/template/compiled_template_loader.go similarity index 75% rename from vendor/github.com/k14s/ytt/pkg/template/compiled_template_loader.go rename to vendor/carvel.dev/ytt/pkg/template/compiled_template_loader.go index f1b86889a..e89c32f3f 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/compiled_template_loader.go +++ b/vendor/carvel.dev/ytt/pkg/template/compiled_template_loader.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -10,7 +10,7 @@ import ( ) type CompiledTemplateLoader interface { - FindCompiledTemplate(string) (*CompiledTemplate, error) + FindCompiledTemplate(string) *CompiledTemplate Load(*starlark.Thread, string) (starlark.StringDict, error) } @@ -24,11 +24,9 @@ func NewNoopCompiledTemplateLoader(tpl *CompiledTemplate) NoopCompiledTemplateLo var _ CompiledTemplateLoader = NoopCompiledTemplateLoader{} -func (l NoopCompiledTemplateLoader) FindCompiledTemplate(_ string) (*CompiledTemplate, error) { - if l.tpl != nil { - return l.tpl, nil - } - return nil, fmt.Errorf("FindCompiledTemplate is not supported") +// FindCompiledTemplate returns the CompiledTemplate this CompiledTemplateLoader was constructed with. +func (l NoopCompiledTemplateLoader) FindCompiledTemplate(_ string) *CompiledTemplate { + return l.tpl } func (l NoopCompiledTemplateLoader) Load( diff --git a/vendor/github.com/k14s/ytt/pkg/template/core/args.go b/vendor/carvel.dev/ytt/pkg/template/core/args.go similarity index 78% rename from vendor/github.com/k14s/ytt/pkg/template/core/args.go rename to vendor/carvel.dev/ytt/pkg/template/core/args.go index dc022b1fc..3de119480 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/core/args.go +++ b/vendor/carvel.dev/ytt/pkg/template/core/args.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package core @@ -9,7 +9,8 @@ import ( "github.com/k14s/starlark-go/starlark" ) -func BoolArg(kwargs []starlark.Tuple, keyToFind string) (bool, error) { +// BoolArg return a boolean value from starlark.Tupe based on a given key, defaults to defaultValue. +func BoolArg(kwargs []starlark.Tuple, keyToFind string, defaultValue bool) (bool, error) { for _, arg := range kwargs { key, err := NewStarlarkValue(arg.Index(0)).AsString() if err != nil { @@ -19,7 +20,7 @@ func BoolArg(kwargs []starlark.Tuple, keyToFind string) (bool, error) { return NewStarlarkValue(arg.Index(1)).AsBool() } } - return false, nil + return defaultValue, nil } func Int64Arg(kwargs []starlark.Tuple, keyToFind string) (int64, error) { diff --git a/vendor/carvel.dev/ytt/pkg/template/core/doc.go b/vendor/carvel.dev/ytt/pkg/template/core/doc.go new file mode 100644 index 000000000..26ccc3d34 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/template/core/doc.go @@ -0,0 +1,7 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package core provides facilities for low-level integration with Starlark. +*/ +package core diff --git a/vendor/github.com/k14s/ytt/pkg/template/core/errs.go b/vendor/carvel.dev/ytt/pkg/template/core/errs.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/template/core/errs.go rename to vendor/carvel.dev/ytt/pkg/template/core/errs.go index 3adf52205..95b9c74b4 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/core/errs.go +++ b/vendor/carvel.dev/ytt/pkg/template/core/errs.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package core diff --git a/vendor/github.com/k14s/ytt/pkg/template/core/go_value.go b/vendor/carvel.dev/ytt/pkg/template/core/go_value.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/template/core/go_value.go rename to vendor/carvel.dev/ytt/pkg/template/core/go_value.go index d9b5ca331..771ed95c8 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/core/go_value.go +++ b/vendor/carvel.dev/ytt/pkg/template/core/go_value.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package core @@ -6,8 +6,8 @@ package core import ( "fmt" + "carvel.dev/ytt/pkg/orderedmap" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/orderedmap" ) type GoValueToStarlarkValueConversion interface { diff --git a/vendor/github.com/k14s/ytt/pkg/template/core/starlark_noop.go b/vendor/carvel.dev/ytt/pkg/template/core/starlark_noop.go similarity index 93% rename from vendor/github.com/k14s/ytt/pkg/template/core/starlark_noop.go rename to vendor/carvel.dev/ytt/pkg/template/core/starlark_noop.go index e7a215856..13a2ebed1 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/core/starlark_noop.go +++ b/vendor/carvel.dev/ytt/pkg/template/core/starlark_noop.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package core diff --git a/vendor/github.com/k14s/ytt/pkg/template/core/starlark_struct.go b/vendor/carvel.dev/ytt/pkg/template/core/starlark_struct.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/template/core/starlark_struct.go rename to vendor/carvel.dev/ytt/pkg/template/core/starlark_struct.go index c1f527cb6..4ddc427ff 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/core/starlark_struct.go +++ b/vendor/carvel.dev/ytt/pkg/template/core/starlark_struct.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package core @@ -6,8 +6,8 @@ package core import ( "fmt" + "carvel.dev/ytt/pkg/orderedmap" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/orderedmap" ) type StarlarkStruct struct { diff --git a/vendor/github.com/k14s/ytt/pkg/template/core/starlark_value.go b/vendor/carvel.dev/ytt/pkg/template/core/starlark_value.go similarity index 89% rename from vendor/github.com/k14s/ytt/pkg/template/core/starlark_value.go rename to vendor/carvel.dev/ytt/pkg/template/core/starlark_value.go index 11ef50eac..22b56dc98 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/core/starlark_value.go +++ b/vendor/carvel.dev/ytt/pkg/template/core/starlark_value.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package core @@ -6,8 +6,8 @@ package core import ( "fmt" + "carvel.dev/ytt/pkg/orderedmap" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/orderedmap" ) type StarlarkValueToGoValueConversion interface { @@ -57,6 +57,17 @@ func (e StarlarkValue) AsInt64() (int64, error) { return 0, fmt.Errorf("expected starlark.Int") } +// AsFloat64 converts a Starlark number (either int or float) to the corresponding Go double-precision float. +func (e StarlarkValue) AsFloat64() (float64, error) { + switch e := e.val.(type) { + case starlark.Int: + return float64(e.Float()), nil + case starlark.Float: + return float64(e), nil + } + return 0, fmt.Errorf("expected float value, but was %T", e.val) +} + func (e StarlarkValue) asInterface(val starlark.Value) (interface{}, error) { if obj, ok := val.(UnconvertableStarlarkValue); ok { return nil, fmt.Errorf("Unable to convert value: %s", obj.ConversionHint()) diff --git a/vendor/carvel.dev/ytt/pkg/template/doc.go b/vendor/carvel.dev/ytt/pkg/template/doc.go new file mode 100644 index 000000000..6c6dcf00b --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/template/doc.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package template provides the core templating engine for ytt. + +At its heart, a template is text (possibly of a specific format like YAML) that +is parsed into a set of template.EvaluationNode's which is then compiled into a +Starlark program whose objective is to build an output structure that reflects +the evaluated expressions that were annotated in the original text. +*/ +package template diff --git a/vendor/github.com/k14s/ytt/pkg/template/evaluation_ctx.go b/vendor/carvel.dev/ytt/pkg/template/evaluation_ctx.go similarity index 95% rename from vendor/github.com/k14s/ytt/pkg/template/evaluation_ctx.go rename to vendor/carvel.dev/ytt/pkg/template/evaluation_ctx.go index 3d6fd5a18..2d067f8ec 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/evaluation_ctx.go +++ b/vendor/carvel.dev/ytt/pkg/template/evaluation_ctx.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -6,8 +6,8 @@ package template import ( "fmt" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template/core" // Should not import template specific packages here (like yamlmeta) ) @@ -156,24 +156,27 @@ func (e *EvaluationCtx) TplStartNodeAnnotation( if err != nil { return starlark.None, err } - annName := AnnotationName(annNameStr) - annVals := args.Index(2).(starlark.Tuple) + annVals := args.Index(2).(starlark.Tuple) kwargs = []starlark.Tuple{} for _, val := range annVals[1:] { kwargs = append(kwargs, val.(starlark.Tuple)) } + ann, ok := e.nodes.FindAnnotation(nodeTag, annName) + if !ok { + return starlark.None, fmt.Errorf("expected to find %v on node %s", annName, nodeTag) + } + ann.Args = annVals[0].(starlark.Tuple) + ann.Kwargs = kwargs + if _, found := e.pendingAnnotations[nodeTag]; !found { e.pendingAnnotations[nodeTag] = NodeAnnotations{} } // TODO overrides last set value - e.pendingAnnotations[nodeTag][annName] = NodeAnnotation{ - Args: annVals[0].(starlark.Tuple), - Kwargs: kwargs, - } + e.pendingAnnotations[nodeTag][annName] = ann return starlark.None, nil } diff --git a/vendor/github.com/k14s/ytt/pkg/template/instructions.go b/vendor/carvel.dev/ytt/pkg/template/instructions.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/template/instructions.go rename to vendor/carvel.dev/ytt/pkg/template/instructions.go index bb056898a..6ea2db4d5 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/instructions.go +++ b/vendor/carvel.dev/ytt/pkg/template/instructions.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -58,6 +58,7 @@ func (is *InstructionSet) NewEndCtxNone() Instruction { func (is *InstructionSet) NewStartNodeAnnotation(nodeTag NodeTag, ann Annotation) Instruction { collectedArgs := is.CollectNodeAnnotation.WithArgs(ann.Content).AsString() + return is.StartNodeAnnotation.WithArgs(nodeTag.AsString(), `"`+string(ann.Name)+`"`, collectedArgs) } diff --git a/vendor/carvel.dev/ytt/pkg/template/meta.go b/vendor/carvel.dev/ytt/pkg/template/meta.go new file mode 100644 index 000000000..f6cdfa96b --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/template/meta.go @@ -0,0 +1,79 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package template + +import ( + "fmt" + "strings" + + "carvel.dev/ytt/pkg/filepos" +) + +type AnnotationName string +type AnnotationNs string + +const ( + // AnnotationComment contains user-facing documentation and should be ignored. + AnnotationComment AnnotationName = "comment" + // AnnotationCode contains Starlark code that should be inserted, verbatim, into the compiled template. + AnnotationCode AnnotationName = "template/code" + // AnnotationValue contains a Starlark expression, the result of which should be set as the value of the annotated node. + AnnotationValue AnnotationName = "template/value" +) + +type Annotation struct { + Name AnnotationName // eg template/code + Content string // eg if True: + Position *filepos.Position +} + +// Supported formats: +// "! comment" +// "@comment content" +// "@ if True:" +// "@template/code" +// "@template/code if True:" +// "@text/trim-left,text/trim-right,template/code if True:" + +type MetaOpts struct { + IgnoreUnknown bool +} + +// NewAnnotationFromComment constructs an Annotation from a string and position from a Comment. +// +// if opts.IgnoreUnknown is true and the annotation is unknown, it is returned as a comment. +// if opts.IgnoreUnknown is false and the annotation is unknown, returns an error. +func NewAnnotationFromComment(data string, position *filepos.Position, opts MetaOpts) (Annotation, error) { + position = position.DeepCopy() + switch { + case len(data) > 0 && data[0] == '!': + return Annotation{ + Name: AnnotationComment, + Content: data[1:], + Position: position, + }, nil + + case len(data) > 0 && data[0] == '@': + nameAndContent := strings.SplitN(data[1:], " ", 2) + ann := Annotation{ + Name: AnnotationName(nameAndContent[0]), + Position: position, + } + if len(nameAndContent) == 2 { + ann.Content = nameAndContent[1] + } + return ann, nil + + default: + if opts.IgnoreUnknown { + return Annotation{ + Name: AnnotationComment, + Content: data, + Position: position, + }, nil + } else { + return Annotation{}, fmt.Errorf("Expected ytt-formatted string (use '#@' for annotations or code, '#!' for comments)") + } + } +} diff --git a/vendor/carvel.dev/ytt/pkg/template/nodes.go b/vendor/carvel.dev/ytt/pkg/template/nodes.go new file mode 100644 index 000000000..179989956 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/template/nodes.go @@ -0,0 +1,97 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package template + +import ( + "strconv" + + "carvel.dev/ytt/pkg/template/core" + "github.com/k14s/starlark-go/starlark" +) + +var ( + NodeTagRoot = NodeTag{-100} +) + +// Nodes contain source information that is used when building and compiling a template. +// +// Nodes track a source's structure by: +// - assigning a unique integer id, NodeTag, for each 'Node'. +// - storing breadcrumbs to find a Node's Parent. +// - keeping track each Node's non-template comments via annotations. +type Nodes struct { + id int + tagToNode map[NodeTag]EvaluationNode + childToParentTag map[NodeTag]NodeTag + annotations map[NodeTag]NodeAnnotations +} + +// NewNodes initializes Nodes with empty maps to store info about the source template. +func NewNodes() *Nodes { + return &Nodes{ + tagToNode: map[NodeTag]EvaluationNode{}, + childToParentTag: map[NodeTag]NodeTag{}, + annotations: map[NodeTag]NodeAnnotations{}, + } +} + +func (n *Nodes) Ancestors() Ancestors { return NewAncestors(n.childToParentTag) } + +// AddRootNode creates a new unique NodeTag to keep track of an EvaluationNode that has no parent. +func (n *Nodes) AddRootNode(node EvaluationNode) NodeTag { + n.id++ + tag := NodeTag{n.id} + n.tagToNode[tag] = node + n.childToParentTag[tag] = NodeTagRoot + return tag +} + +// AddNode creates a new unique NodeTag to keep track of the EvaluationNode and its parent. +func (n *Nodes) AddNode(node EvaluationNode, parentTag NodeTag) NodeTag { + n.id++ + tag := NodeTag{n.id} + n.tagToNode[tag] = node + n.childToParentTag[tag] = parentTag + return tag +} + +// FindNode uses a NodeTag to retrieve an EvaluationNode from the annotations map in Nodes. +func (n *Nodes) FindNode(tag NodeTag) (EvaluationNode, bool) { + node, ok := n.tagToNode[tag] + return node, ok +} + +// AddAnnotation creates an entry in the annotations map of Nodes. +// The entry is NodeAnnotation with only the annotation's position, +// indexed by NodeTag and AnnotationName. +func (n *Nodes) AddAnnotation(tag NodeTag, ann Annotation) { + if _, found := n.annotations[tag]; !found { + n.annotations[tag] = NodeAnnotations{} + } + n.annotations[tag][ann.Name] = NodeAnnotation{Position: ann.Position} +} + +// FindAnnotation uses a NodeTag, and an AnnotationName to retrieve a NodeAnnotation from the annotations map in Nodes. +func (n *Nodes) FindAnnotation(tag NodeTag, annName AnnotationName) (NodeAnnotation, bool) { + ann, ok := n.annotations[tag][annName] + return ann, ok +} + +type NodeTag struct { + id int +} + +func NewNodeTag(id int) NodeTag { return NodeTag{id} } + +func NewNodeTagFromStarlarkValue(val starlark.Value) (NodeTag, error) { + id, err := core.NewStarlarkValue(val).AsInt64() + if err != nil { + return NodeTag{}, err + } + return NodeTag{int(id)}, nil +} + +func (t NodeTag) Equals(other NodeTag) bool { return t.id == other.id } +func (t NodeTag) String() string { return "node tag " + strconv.Itoa(t.id) } +func (t NodeTag) AsString() string { return strconv.Itoa(t.id) } diff --git a/vendor/github.com/k14s/ytt/pkg/template/program_ast.go b/vendor/carvel.dev/ytt/pkg/template/program_ast.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/template/program_ast.go rename to vendor/carvel.dev/ytt/pkg/template/program_ast.go index e04c01366..101f14387 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/program_ast.go +++ b/vendor/carvel.dev/ytt/pkg/template/program_ast.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template diff --git a/vendor/github.com/k14s/ytt/pkg/template/source.go b/vendor/carvel.dev/ytt/pkg/template/source.go similarity index 93% rename from vendor/github.com/k14s/ytt/pkg/template/source.go rename to vendor/carvel.dev/ytt/pkg/template/source.go index 0061ee14b..c716a29c3 100644 --- a/vendor/github.com/k14s/ytt/pkg/template/source.go +++ b/vendor/carvel.dev/ytt/pkg/template/source.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package template @@ -6,7 +6,7 @@ package template import ( "bytes" - "github.com/k14s/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/filepos" ) type Line struct { diff --git a/vendor/github.com/k14s/ytt/pkg/texttemplate/ast.go b/vendor/carvel.dev/ytt/pkg/texttemplate/ast.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/texttemplate/ast.go rename to vendor/carvel.dev/ytt/pkg/texttemplate/ast.go index 3575d8c9b..dcce51414 100644 --- a/vendor/github.com/k14s/ytt/pkg/texttemplate/ast.go +++ b/vendor/carvel.dev/ytt/pkg/texttemplate/ast.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package texttemplate @@ -6,8 +6,8 @@ package texttemplate import ( "fmt" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" ) type NodeRoot struct { @@ -49,9 +49,7 @@ func (n *NodeRoot) AsString() string { func (n *NodeRoot) GetValues() []interface{} { var result []interface{} - for _, item := range n.Items { - result = append(result, item) - } + result = append(result, n.Items...) return result } diff --git a/vendor/carvel.dev/ytt/pkg/texttemplate/doc.go b/vendor/carvel.dev/ytt/pkg/texttemplate/doc.go new file mode 100644 index 000000000..e579059fa --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/texttemplate/doc.go @@ -0,0 +1,7 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package texttemplate implements the text dialect of the ytt templating engine. +*/ +package texttemplate diff --git a/vendor/github.com/k14s/ytt/pkg/texttemplate/evaluation_ctx.go b/vendor/carvel.dev/ytt/pkg/texttemplate/evaluation_ctx.go similarity index 93% rename from vendor/github.com/k14s/ytt/pkg/texttemplate/evaluation_ctx.go rename to vendor/carvel.dev/ytt/pkg/texttemplate/evaluation_ctx.go index c021c874d..0eea5c36c 100644 --- a/vendor/github.com/k14s/ytt/pkg/texttemplate/evaluation_ctx.go +++ b/vendor/carvel.dev/ytt/pkg/texttemplate/evaluation_ctx.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package texttemplate @@ -6,7 +6,7 @@ package texttemplate import ( "fmt" - "github.com/k14s/ytt/pkg/template" + "carvel.dev/ytt/pkg/template" ) const ( diff --git a/vendor/github.com/k14s/ytt/pkg/texttemplate/metas.go b/vendor/carvel.dev/ytt/pkg/texttemplate/metas.go similarity index 74% rename from vendor/github.com/k14s/ytt/pkg/texttemplate/metas.go rename to vendor/carvel.dev/ytt/pkg/texttemplate/metas.go index 1705f4111..9e3f3ec80 100644 --- a/vendor/github.com/k14s/ytt/pkg/texttemplate/metas.go +++ b/vendor/carvel.dev/ytt/pkg/texttemplate/metas.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package texttemplate @@ -11,7 +11,8 @@ type NodeCodeMeta struct { *NodeCode } -func (p NodeCodeMeta) ShoudTrimSpaceLeft() bool { +// ShouldTrimSpaceLeft indicates whether leading spaces should be removed (because the left-trim token, `-`, was present) +func (p NodeCodeMeta) ShouldTrimSpaceLeft() bool { return strings.HasPrefix(p.Content, "-") } diff --git a/vendor/github.com/k14s/ytt/pkg/texttemplate/parser.go b/vendor/carvel.dev/ytt/pkg/texttemplate/parser.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/texttemplate/parser.go rename to vendor/carvel.dev/ytt/pkg/texttemplate/parser.go index b6542e899..745802b3b 100644 --- a/vendor/github.com/k14s/ytt/pkg/texttemplate/parser.go +++ b/vendor/carvel.dev/ytt/pkg/texttemplate/parser.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package texttemplate @@ -6,7 +6,7 @@ package texttemplate import ( "fmt" - "github.com/k14s/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/filepos" ) type Parser struct { @@ -102,7 +102,5 @@ func (p *Parser) parse(dataBs []byte, associatedName string, startPos *filepos.P } func (p *Parser) newPosition(line int) *filepos.Position { - pos := filepos.NewPosition(line) - pos.SetFile(p.associatedName) - return pos + return filepos.NewPositionInFile(line, p.associatedName) } diff --git a/vendor/github.com/k14s/ytt/pkg/texttemplate/template.go b/vendor/carvel.dev/ytt/pkg/texttemplate/template.go similarity index 96% rename from vendor/github.com/k14s/ytt/pkg/texttemplate/template.go rename to vendor/carvel.dev/ytt/pkg/texttemplate/template.go index 375d90825..f469541ba 100644 --- a/vendor/github.com/k14s/ytt/pkg/texttemplate/template.go +++ b/vendor/carvel.dev/ytt/pkg/texttemplate/template.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package texttemplate @@ -8,7 +8,7 @@ import ( "strings" "unicode" - "github.com/k14s/ytt/pkg/template" + "carvel.dev/ytt/pkg/template" ) type Template struct { @@ -80,7 +80,7 @@ func (e *Template) compile(rootNode *NodeRoot, meta := NodeCodeMeta{typedNode} trimSpaceRight = meta.ShouldTrimSpaceRight() - if meta.ShoudTrimSpaceLeft() && i != 0 { + if meta.ShouldTrimSpaceLeft() && i != 0 { if typedLastNode, ok := rootNode.Items[i-1].(*NodeText); ok { typedLastNode.Content = strings.TrimRightFunc( typedLastNode.Content, unicode.IsSpace) diff --git a/vendor/carvel.dev/ytt/pkg/validations/annotations.go b/vendor/carvel.dev/ytt/pkg/validations/annotations.go new file mode 100644 index 000000000..954329752 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/validations/annotations.go @@ -0,0 +1,186 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package validations + +import ( + "fmt" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" + "github.com/k14s/starlark-go/starlark" +) + +// Declare @assert/... annotation and keyword argument names +const ( + AnnotationAssertValidate template.AnnotationName = "assert/validate" + + KwargWhen string = "when" + KwargMinLength string = "min_len" + KwargMaxLength string = "max_len" + KwargMin string = "min" + KwargMax string = "max" + KwargNotNull string = "not_null" + KwargOneNotNull string = "one_not_null" + KwargOneOf string = "one_of" +) + +// ProcessAssertValidateAnns checks Assert annotations on data values and stores them on a Node as Validations. +// Returns an error if any Assert annotations are malformed. +func ProcessAssertValidateAnns(rootNode yamlmeta.Node) error { + if rootNode == nil { + return nil + } + return yamlmeta.Walk(rootNode, &convertAssertAnnsToValidations{}) +} + +type convertAssertAnnsToValidations struct{} + +// Visit if `node` is annotated with `@assert/validate` (AnnotationAssertValidate). +// Checks annotation, and stores the validationRun on Node's validations meta. +// +// This visitor returns and error if any assert annotation is not well-formed, +// otherwise, returns nil. +func (a *convertAssertAnnsToValidations) Visit(node yamlmeta.Node) error { + nodeAnnotations := template.NewAnnotations(node) + if !nodeAnnotations.Has(AnnotationAssertValidate) { + return nil + } + switch node.(type) { + case *yamlmeta.DocumentSet, *yamlmeta.Array, *yamlmeta.Map: + return fmt.Errorf("Invalid @%s annotation - not supported on %s at %s", AnnotationAssertValidate, yamlmeta.TypeName(node), node.GetPosition().AsCompactString()) + default: + validation, err := NewValidationFromAnn(nodeAnnotations[AnnotationAssertValidate]) + if err != nil { + return fmt.Errorf("Invalid @%s annotation - %s", AnnotationAssertValidate, err.Error()) + } + // store rules in node's validations meta without overriding any existing rules + Add(node, []NodeValidation{*validation}) + } + + return nil +} + +// NewValidationFromAnn creates a NodeValidation from the values provided in a validationRun-style annotation. +func NewValidationFromAnn(annotation template.NodeAnnotation) (*NodeValidation, error) { + var rules []rule + if len(annotation.Args) == 0 && len(annotation.Kwargs) == 0 { + return nil, fmt.Errorf("expected annotation to have 2-tuple as argument(s), but found no arguments (by %s)", annotation.Position.AsCompactString()) + } + for _, arg := range annotation.Args { + ruleTuple, ok := arg.(starlark.Tuple) + if !ok { + return nil, fmt.Errorf("expected annotation to have 2-tuple as argument(s), but found: %s (by %s)", arg.String(), annotation.Position.AsCompactString()) + } + if len(ruleTuple) != 2 { + return nil, fmt.Errorf("expected 2-tuple, but found tuple with length %v (by %s)", len(ruleTuple), annotation.Position.AsCompactString()) + } + + message, ok := ruleTuple[0].(starlark.String) + if !ok { + return nil, fmt.Errorf("expected first item in the 2-tuple to be a string describing a valid value, but was %s (at %s)", ruleTuple[0].Type(), annotation.Position.AsCompactString()) + } + + assertion, ok := ruleTuple[1].(starlark.Callable) + if !ok { + var err error + assertion, err = assertionFromCheckAttr(ruleTuple[1]) + if err != nil { + return nil, fmt.Errorf("%s (at %s)", err, annotation.Position.AsCompactString()) + } + } + rules = append(rules, rule{ + msg: message.GoString(), + assertion: assertion, + }) + } + kwargs, err := newValidationKwargs(annotation.Kwargs, annotation.Position) + if err != nil { + return nil, err + } + + rules = append(rules, kwargs.asRules()...) + + return &NodeValidation{rules, kwargs, annotation.Position}, nil +} + +func assertionFromCheckAttr(value starlark.Value) (starlark.Callable, error) { + val, hasAttrs := value.(starlark.HasAttrs) + if !hasAttrs { + return nil, fmt.Errorf("expected second item in the 2-tuple to be an assertion function, but was %s", value.Type()) + } + + checkAttr, err := val.Attr("check") + if err != nil || (checkAttr == nil && err == nil) { + return nil, fmt.Errorf("expected second item in tuple to be an assertion function or assertion object, but was a %s", value.Type()) + } + + assertionFunc, ok := checkAttr.(starlark.Callable) + if !ok { + return nil, fmt.Errorf("expected struct with attribute check(), but was %s", checkAttr.Type()) + } + + return assertionFunc, nil +} + +// newValidationKwargs takes the keyword arguments from a Validation annotation, +// and makes sure they are well-formed. +func newValidationKwargs(kwargs []starlark.Tuple, annPos *filepos.Position) (validationKwargs, error) { + var processedKwargs validationKwargs + for _, value := range kwargs { + kwargName := string(value[0].(starlark.String)) + switch kwargName { + case KwargWhen: + v, ok := value[1].(starlark.Callable) + if !ok { + return validationKwargs{}, fmt.Errorf("expected keyword argument %q to be a function, but was %s (at %s)", KwargWhen, value[1].Type(), annPos.AsCompactString()) + } + processedKwargs.when = v + case KwargMinLength: + v, err := starlark.NumberToInt(value[1]) + if err != nil { + return validationKwargs{}, fmt.Errorf("expected keyword argument %q to be a number, but was %s (at %s)", KwargMinLength, value[1].Type(), annPos.AsCompactString()) + } + processedKwargs.minLength = &v + case KwargMaxLength: + v, err := starlark.NumberToInt(value[1]) + if err != nil { + return validationKwargs{}, fmt.Errorf("expected keyword argument %q to be a number, but was %s (at %s)", KwargMaxLength, value[1].Type(), annPos.AsCompactString()) + } + processedKwargs.maxLength = &v + case KwargMin: + processedKwargs.min = value[1] + case KwargMax: + processedKwargs.max = value[1] + case KwargNotNull: + v, ok := value[1].(starlark.Bool) + if !ok { + return validationKwargs{}, fmt.Errorf("expected keyword argument %q to be a boolean, but was %s (at %s)", KwargNotNull, value[1].Type(), annPos.AsCompactString()) + } + processedKwargs.notNull = bool(v) + case KwargOneNotNull: + switch v := value[1].(type) { + case starlark.Bool: + if v { + processedKwargs.oneNotNull = v + } else { + return validationKwargs{}, fmt.Errorf("one_not_null= cannot be False") + } + case starlark.Sequence: + processedKwargs.oneNotNull = v + default: + return validationKwargs{}, fmt.Errorf("expected True or a sequence of keys, but was a '%s'", value[1].Type()) + } + case KwargOneOf: + v, ok := value[1].(starlark.Sequence) + if !ok { + return validationKwargs{}, fmt.Errorf("expected keyword argument %s to be a sequence, but was %s", KwargOneOf, value[1].Type()) + } + processedKwargs.oneOf = v + default: + return validationKwargs{}, fmt.Errorf("unknown keyword argument %q (at %s)", kwargName, annPos.AsCompactString()) + } + } + return processedKwargs, nil +} diff --git a/vendor/carvel.dev/ytt/pkg/validations/doc.go b/vendor/carvel.dev/ytt/pkg/validations/doc.go new file mode 100644 index 000000000..77e98ec2b --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/validations/doc.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package validations enriches YAML structures by attaching user-defined +constraints (that is, validationRun rules) onto individual yamlmeta.Node's. + +# Validations on Data Values + +While "@data/values" can technically be annotated with "@assert/validate" +annotations, it is expected that authors will use "@schema/validationRun" in +"@data/values-schema" documents instead. +*/ +package validations diff --git a/vendor/carvel.dev/ytt/pkg/validations/validate.go b/vendor/carvel.dev/ytt/pkg/validations/validate.go new file mode 100644 index 000000000..45d2c759e --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/validations/validate.go @@ -0,0 +1,427 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package validations + +import ( + "fmt" + "reflect" + "sort" + "strings" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" + "carvel.dev/ytt/pkg/yttlibrary" + "github.com/k14s/starlark-go/starlark" +) + +// NodeValidation represents a validationRun attached to a Node via an annotation. +type NodeValidation struct { + rules []rule + kwargs validationKwargs + position *filepos.Position +} + +// A rule contains a string description of what constitutes a valid value, +// and a function that asserts the rule against an actual value. +type rule struct { + msg string + assertion starlark.Callable + priority int // how early to run this rule. 0 = order it appears; more positive: earlier, more negative: later. + isCritical bool // whether not satisfying this rule prevents others rules from running. +} + +// byPriority sorts (a copy) of "rules" by priority in descending order (i.e. the order in which the rules should run) +func byPriority(rules []rule) []rule { + sorted := make([]rule, len(rules)) + copy(sorted, rules) + sort.SliceStable(sorted, func(idx, jdx int) bool { + return sorted[idx].priority > sorted[jdx].priority + }) + return sorted +} + +// validationKwargs represent the optional keyword arguments and their values in a validationRun annotation. +type validationKwargs struct { + when starlark.Callable + minLength *starlark.Int // 0 len("") == 0, this always passes + maxLength *starlark.Int + min starlark.Value + max starlark.Value + notNull bool + oneNotNull starlark.Value // valid values are either starlark.Sequence or starlark.Bool + oneOf starlark.Sequence +} + +// Run takes a root Node, and threadName, and validates each Node in the tree. +// +// When a Node's value is invalid, the errors are collected and returned in a Check. +// Otherwise, returns empty Check and nil error. +func Run(node yamlmeta.Node, threadName string) (Check, error) { + if node == nil { + return Check{}, nil + } + + validation := newValidationRun(threadName, node) + err := yamlmeta.WalkWithParent(node, nil, "", validation) + if err != nil { + return Check{}, err + } + + return validation.chk, nil +} + +type validationRun struct { + thread *starlark.Thread + chk Check + root yamlmeta.Node +} + +func newValidationRun(threadName string, root yamlmeta.Node) *validationRun { + return &validationRun{thread: &starlark.Thread{Name: threadName}, root: root} +} + +// VisitWithParent if `node` has validations in its meta. +// Runs those validations, collecting any violations +// +// This visitor stores error(violations) in the validationRun and returns nil. +func (a *validationRun) VisitWithParent(value yamlmeta.Node, parent yamlmeta.Node, path string) error { + // get rules in node's meta + validations := Get(value) + + if validations == nil { + return nil + } + for _, v := range validations { + invalid, err := v.Validate(value, parent, a.root, path, a.thread) + if err != nil { + return err + } + if len(invalid.Violations) > 0 { + a.chk.Invalidations = append(a.chk.Invalidations, invalid) + } + } + + return nil +} + +// HasSimpleMinLength indicates presence of min length validation and its associated value. +// Returns false if validation is conditional (via when=). +func (v NodeValidation) HasSimpleMinLength() (int64, bool) { + if v.kwargs.when != nil { + return 0, false + } + if v.kwargs.minLength != nil { + value, ok := v.kwargs.minLength.Int64() + if ok { + return value, true + } + } + return 0, false +} + +// HasSimpleMaxLength indicates presence of max length validation and its associated value. +// Returns false if validation is conditional (via when=). +func (v NodeValidation) HasSimpleMaxLength() (int64, bool) { + if v.kwargs.when != nil { + return 0, false + } + if v.kwargs.maxLength != nil { + value, ok := v.kwargs.maxLength.Int64() + if ok { + return value, true + } + } + return 0, false +} + +// HasSimpleMin indicates presence of min validation and its associated value. +// Returns false if validation is conditional (via when=). +func (v NodeValidation) HasSimpleMin() (interface{}, bool) { + if v.kwargs.when != nil { + return nil, false + } + if v.kwargs.min != nil { + value, err := core.NewStarlarkValue(v.kwargs.min).AsGoValue() + if err == nil { + return value, true + } + } + return nil, false +} + +// HasSimpleMax indicates presence of max validation and its associated value. +// Returns false if validation is conditional (via when=). +func (v NodeValidation) HasSimpleMax() (interface{}, bool) { + if v.kwargs.when != nil { + return nil, false + } + if v.kwargs.max != nil { + value, err := core.NewStarlarkValue(v.kwargs.max).AsGoValue() + if err == nil { + return value, true + } + } + return nil, false +} + +// HasSimpleOneOf indicates presence of one-of validation and its allowed values. +// Returns false if validation is conditional (via when=). +func (v NodeValidation) HasSimpleOneOf() ([]interface{}, bool) { + if v.kwargs.when != nil { + return nil, false + } + if v.kwargs.oneOf != nil { + enum := []interface{}{} + iter := starlark.Iterate(v.kwargs.oneOf) + defer iter.Done() + var x starlark.Value + for iter.Next(&x) { + value, err := core.NewStarlarkValue(x).AsGoValue() + if err == nil { + enum = append(enum, value) + } else { + return nil, false + } + } + return enum, true + } + return nil, false +} + +// Validate runs the assertions in the rules with the node's value as arguments IF +// the ValidationKwargs conditional options pass. +// +// Returns an error if the assertion returns False (not-None), or assert.fail()s. +// Otherwise, returns nil. +func (v NodeValidation) Validate(node yamlmeta.Node, parent yamlmeta.Node, root yamlmeta.Node, path string, thread *starlark.Thread) (Invalidation, error) { + nodeValue := v.newStarlarkValue(node) + parentValue := v.newStarlarkValue(parent) + rootValue := v.newStarlarkValue(root) + + executeRules, err := v.kwargs.shouldValidate(nodeValue, parentValue, thread, rootValue) + if err != nil { + return Invalidation{}, fmt.Errorf("Validating %s: %s", path, err) + } + if !executeRules { + return Invalidation{}, nil + } + + displayedPath := path + if displayedPath == "" { + displayedPath = fmt.Sprintf("(%s)", yamlmeta.TypeName(node)) + } + invalid := Invalidation{ + Path: displayedPath, + ValueSource: node.GetPosition(), + } + + for _, rul := range byPriority(v.rules) { + result, err := starlark.Call(thread, rul.assertion, starlark.Tuple{nodeValue}, []starlark.Tuple{}) + if err != nil { + violation := Violation{ + RuleSource: v.position, + Description: rul.msg, + Results: strings.TrimPrefix(strings.TrimPrefix(err.Error(), "fail: "), "check: "), + } + invalid.Violations = append(invalid.Violations, violation) + if rul.isCritical { + break + } + } else { + if !(result == starlark.True) { + violation := Violation{ + RuleSource: v.position, + Description: rul.msg, + Results: "", + } + invalid.Violations = append(invalid.Violations, violation) + if rul.isCritical { + break + } + } + } + } + return invalid, nil +} + +// shouldValidate uses validationKwargs and the node's value to run checks on the value. If the value satisfies the checks, +// then the NodeValidation's rules should execute, otherwise the rules will be skipped. +func (v validationKwargs) shouldValidate(value starlark.Value, parent starlark.Value, thread *starlark.Thread, root starlark.Value) (bool, error) { + _, valueIsNull := value.(starlark.NoneType) + if valueIsNull && !v.notNull { + return false, nil + } + + if v.when != nil && !reflect.ValueOf(v.when).IsNil() { + args, err := v.populateArgs(value, parent, root) + if err != nil { + return false, fmt.Errorf("Failed to evaluate when=: %s", err) + } + + result, err := starlark.Call(thread, v.when, args, []starlark.Tuple{}) + if err != nil { + return false, fmt.Errorf("Failure evaluating when=: %s", err) + } + + resultBool, isBool := result.(starlark.Bool) + if !isBool { + return false, fmt.Errorf("want when= to be bool, got %s", result.Type()) + } + + return bool(resultBool), nil + } + + return true, nil +} + +func (v validationKwargs) populateArgs(value starlark.Value, parent starlark.Value, root starlark.Value) ([]starlark.Value, error) { + args := []starlark.Value{} + args = append(args, value) + + whenFunc := v.when.(*starlark.Function) + switch whenFunc.NumParams() { + case 1: + case 2: + ctx := orderedmap.NewMap() + ctx.Set("parent", parent) + ctx.Set("root", root) + args = append(args, core.NewStarlarkStruct(ctx)) + default: + return nil, fmt.Errorf("function must accept 1 or 2 arguments (%d given)", whenFunc.NumParams()) + } + return args, nil +} + +func (v validationKwargs) asRules() []rule { + var rules []rule + + if v.minLength != nil { + rules = append(rules, rule{ + msg: fmt.Sprintf("length >= %v", *v.minLength), + assertion: yttlibrary.NewAssertMinLen(*v.minLength).CheckFunc(), + }) + } + if v.maxLength != nil { + rules = append(rules, rule{ + msg: fmt.Sprintf("length <= %v", *v.maxLength), + assertion: yttlibrary.NewAssertMaxLen(*v.maxLength).CheckFunc(), + }) + } + if v.min != nil { + rules = append(rules, rule{ + msg: fmt.Sprintf("a value >= %v", v.min), + assertion: yttlibrary.NewAssertMin(v.min).CheckFunc(), + }) + } + if v.max != nil { + rules = append(rules, rule{ + msg: fmt.Sprintf("a value <= %v", v.max), + assertion: yttlibrary.NewAssertMax(v.max).CheckFunc(), + }) + } + if v.notNull { + rules = append(rules, rule{ + msg: "not null", + assertion: yttlibrary.NewAssertNotNull().CheckFunc(), + isCritical: true, + priority: 100, + }) + } + if v.oneNotNull != nil { + var assertion *yttlibrary.Assertion + var childKeys = "" + + switch oneNotNull := v.oneNotNull.(type) { + case starlark.Bool: + if oneNotNull { + assertion = yttlibrary.NewAssertOneNotNull(nil) + childKeys = "all children" + } else { + // should have been caught when args were parsed + panic("one_not_null= cannot be False") + } + case starlark.Sequence: + assertion = yttlibrary.NewAssertOneNotNull(oneNotNull) + childKeys = oneNotNull.String() + default: + // should have been caught when args were parsed + panic(fmt.Sprintf("Unexpected type \"%s\" for one_not_null=", v.oneNotNull.Type())) + } + + rules = append(rules, rule{ + msg: fmt.Sprintf("exactly one of %s to be not null", childKeys), + assertion: assertion.CheckFunc(), + }) + } + if v.oneOf != nil { + rules = append(rules, rule{ + msg: fmt.Sprintf("one of %s", v.oneOf.String()), + assertion: yttlibrary.NewAssertOneOf(v.oneOf).CheckFunc(), + }) + } + + return rules +} + +// Invalidation describes a value that was invalidated, and how. +type Invalidation struct { + Path string + ValueSource *filepos.Position + Violations []Violation +} + +// Violation describes how a value failed to satisfy a rule. +type Violation struct { + RuleSource *filepos.Position + Description string + Results string +} + +// Check holds the complete set of Invalidations (if any) resulting from checking all validation rules. +type Check struct { + Invalidations []Invalidation +} + +// ResultsAsString generates the error message composed of the total set of Check.Invalidations. +func (c Check) ResultsAsString() string { + if !c.HasInvalidations() { + return "" + } + + msg := "" + for _, inval := range c.Invalidations { + msg += fmt.Sprintf(" %s\n from: %s\n", inval.Path, inval.ValueSource.AsCompactString()) + for _, viol := range inval.Violations { + msg += fmt.Sprintf(" - must be: %s (by: %s)\n", viol.Description, viol.RuleSource.AsCompactString()) + if viol.Results != "" { + msg += fmt.Sprintf(" found: %s\n", viol.Results) + } + } + msg += "\n" + } + return msg +} + +// HasInvalidations indicates whether this Check contains any violations. +func (c Check) HasInvalidations() bool { + return len(c.Invalidations) > 0 +} + +func (v NodeValidation) newStarlarkValue(node yamlmeta.Node) starlark.Value { + if node == nil || reflect.ValueOf(node).IsNil() { + return starlark.None + } + + switch node.(type) { + case *yamlmeta.DocumentSet, *yamlmeta.Array, *yamlmeta.Map: + return yamltemplate.NewGoValueWithYAML(node).AsStarlarkValue() + case *yamlmeta.Document, *yamlmeta.MapItem, *yamlmeta.ArrayItem: + return yamltemplate.NewGoValueWithYAML(node.GetValues()[0]).AsStarlarkValue() + default: + panic(fmt.Sprintf("Unexpected node type %T (at or near %s)", node, node.GetPosition().AsCompactString())) + } +} diff --git a/vendor/carvel.dev/ytt/pkg/validations/yamlmeta.go b/vendor/carvel.dev/ytt/pkg/validations/yamlmeta.go new file mode 100644 index 000000000..617ed4202 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/validations/yamlmeta.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package validations + +import ( + "carvel.dev/ytt/pkg/yamlmeta" +) + +const validationsMeta = "validations" + +// Add appends validations to node's validations metadata, later retrieved via Get(). +func Add(node yamlmeta.Node, validations []NodeValidation) { + metas := node.GetMeta(validationsMeta) + if metas != nil { + validations = append(metas.([]NodeValidation), validations...) + } + Set(node, validations) +} + +// Set attaches validations to node's metadata, later retrieved via Get(). +func Set(node yamlmeta.Node, meta []NodeValidation) { + node.SetMeta(validationsMeta, meta) +} + +// Get retrieves validations from node metadata, set previously via Set(). +func Get(node yamlmeta.Node) []NodeValidation { + metas := node.GetMeta(validationsMeta) + if metas == nil { + return nil + } + return metas.([]NodeValidation) +} diff --git a/vendor/carvel.dev/ytt/pkg/version/doc.go b/vendor/carvel.dev/ytt/pkg/version/doc.go new file mode 100644 index 000000000..20b3614aa --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/version/doc.go @@ -0,0 +1,7 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package version is where the version of the ytt binary is set. +*/ +package version diff --git a/vendor/github.com/k14s/ytt/pkg/version/version.go b/vendor/carvel.dev/ytt/pkg/version/version.go similarity index 68% rename from vendor/github.com/k14s/ytt/pkg/version/version.go rename to vendor/carvel.dev/ytt/pkg/version/version.go index 3ca685ad0..e04d5680b 100644 --- a/vendor/github.com/k14s/ytt/pkg/version/version.go +++ b/vendor/carvel.dev/ytt/pkg/version/version.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package version diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/data_loader.go b/vendor/carvel.dev/ytt/pkg/workspace/data_loader.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/workspace/data_loader.go rename to vendor/carvel.dev/ytt/pkg/workspace/data_loader.go index 21f55f4d9..0f933a866 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/data_loader.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/data_loader.go @@ -1,10 +1,10 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace import ( - "github.com/k14s/ytt/pkg/files" + "carvel.dev/ytt/pkg/files" ) type DataLoader struct { diff --git a/vendor/carvel.dev/ytt/pkg/workspace/data_values_pre_processing.go b/vendor/carvel.dev/ytt/pkg/workspace/data_values_pre_processing.go new file mode 100644 index 000000000..3bae0c370 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/data_values_pre_processing.go @@ -0,0 +1,175 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package workspace + +import ( + "fmt" + "strings" + + "carvel.dev/ytt/pkg/schema" + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/yamlmeta" + yttoverlay "carvel.dev/ytt/pkg/yttlibrary/overlay" + "github.com/k14s/starlark-go/starlark" +) + +// DataValuesPreProcessing combines all data values documents (and any overlays) into a result set. +type DataValuesPreProcessing struct { + valuesFiles []*FileInLibrary + valuesOverlays []*datavalues.Envelope + schema *datavalues.Schema + loader *TemplateLoader + rootLibrary *Library +} + +// Apply executes the pre-processing of data values for all libraries. +// +// Returns the data values for the root library and enveloped data values for children libraries. +func (pp DataValuesPreProcessing) Apply() (*datavalues.Envelope, []*datavalues.Envelope, error) { + files := append([]*FileInLibrary{}, pp.valuesFiles...) + + // Respect assigned file order for data values overlaying to succeed + SortFilesInLibrary(files) + + dataValues, libraryDataValues, err := pp.apply(files) + if err != nil { + errMsg := "Overlaying data values (in following order: %s): %s" + return nil, nil, fmt.Errorf(errMsg, pp.allFileDescs(files), err) + } + + return dataValues, libraryDataValues, nil +} + +func (pp DataValuesPreProcessing) apply(files []*FileInLibrary) (*datavalues.Envelope, []*datavalues.Envelope, error) { + allDvs, err := pp.collectDataValuesDocs(files) + if err != nil { + return nil, nil, err + } + + // merge all Data Values YAML documents into one + var childrenLibDVs []*datavalues.Envelope + var dvsDoc *yamlmeta.Document + for _, dv := range allDvs { + if dv.IntendedForAnotherLibrary() { + childrenLibDVs = append(childrenLibDVs, dv) + continue + } + + if dvsDoc == nil { + dvsDoc = dv.Doc + } else { + dvsDoc, err = pp.overlay(dvsDoc, dv.Doc) + if err != nil { + return nil, nil, err + } + } + typeCheck := pp.typeAndCheck(dvsDoc) + if len(typeCheck.Violations) > 0 { + return nil, nil, schema.NewSchemaError("One or more data values were invalid", typeCheck.Violations...) + } + } + + if dvsDoc == nil { + dvsDoc = datavalues.NewEmptyDataValuesDocument() + } + dataValues, err := datavalues.NewEnvelope(dvsDoc) + if err != nil { + return nil, nil, err + } + + return dataValues, childrenLibDVs, nil +} + +func (pp DataValuesPreProcessing) collectDataValuesDocs(dvFiles []*FileInLibrary) ([]*datavalues.Envelope, error) { + var allDvs []*datavalues.Envelope + if defaults := pp.schema.DefaultDataValues(); defaults != nil { + dv, err := datavalues.NewEnvelope(defaults) + if err != nil { + return nil, err + } + allDvs = append(allDvs, dv) + } + for _, file := range dvFiles { + docs, err := pp.extractDataValueDocs(file) + if err != nil { + return nil, fmt.Errorf("Templating file '%s': %s", file.File.RelativePath(), err) + } + for _, d := range docs { + dv, err := datavalues.NewEnvelope(d) + if err != nil { + return nil, err + } + allDvs = append(allDvs, dv) + } + } + allDvs = append(allDvs, pp.valuesOverlays...) + return allDvs, nil +} + +func (pp DataValuesPreProcessing) typeAndCheck(dataValuesDoc *yamlmeta.Document) schema.TypeCheck { + chk := pp.schema.AssignType(dataValuesDoc) + if len(chk.Violations) > 0 { + return chk + } + + // updates node's validations meta from Node's assigned type + _ = yamlmeta.Walk(dataValuesDoc, schema.AssignSchemaValidations{}) + + chk = schema.CheckNode(dataValuesDoc) + return chk +} + +func (pp DataValuesPreProcessing) extractDataValueDocs(dvFile *FileInLibrary) ([]*yamlmeta.Document, error) { + libraryCtx := LibraryExecutionContext{Current: dvFile.Library, Root: pp.rootLibrary} + + _, resultDocSet, err := pp.loader.EvalYAML(libraryCtx, dvFile.File) + if err != nil { + return nil, err + } + + valuesDocs, nonValuesDocs, err := DocExtractor{resultDocSet}.Extract(datavalues.AnnotationDataValues) + if err != nil { + return nil, err + } + + // For simplicity's sake, prohibit mixing data value documents with other kinds. + if len(nonValuesDocs) > 0 { + for _, doc := range nonValuesDocs { + if !doc.IsEmpty() { + errStr := "Expected data values file '%s' to only have data values documents" + return nil, fmt.Errorf(errStr, dvFile.File.RelativePath()) + } + } + } + + return valuesDocs, nil +} + +func (pp DataValuesPreProcessing) allFileDescs(files []*FileInLibrary) string { + var result []string + for _, f := range files { + result = append(result, f.File.RelativePath()) + } + if len(pp.valuesOverlays) > 0 { + result = append(result, "additional data values") + } + return strings.Join(result, ", ") +} + +func (pp DataValuesPreProcessing) overlay(doc, overlay *yamlmeta.Document) (*yamlmeta.Document, error) { + op := yttoverlay.Op{ + Left: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{doc}}, + Right: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{overlay}}, + Thread: &starlark.Thread{Name: "data-values-pre-processing"}, + + ExactMatch: true, + } + + result, err := op.Apply() + if err != nil { + return nil, err + } + + return result.(*yamlmeta.DocumentSet).Items[0], nil +} diff --git a/vendor/carvel.dev/ytt/pkg/workspace/data_values_schema_pre_processing.go b/vendor/carvel.dev/ytt/pkg/workspace/data_values_schema_pre_processing.go new file mode 100644 index 000000000..7ac9cff1a --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/data_values_schema_pre_processing.go @@ -0,0 +1,152 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package workspace + +import ( + "fmt" + "strings" + + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/yamlmeta" + yttoverlay "carvel.dev/ytt/pkg/yttlibrary/overlay" + "github.com/k14s/starlark-go/starlark" +) + +// DataValuesSchemaPreProcessing combines all data values schema documents (and any overlays) into a result set. +type DataValuesSchemaPreProcessing struct { + schemaFiles []*FileInLibrary + schemaOverlays []*datavalues.SchemaEnvelope + loader *TemplateLoader + rootLibrary *Library +} + +// Apply executes the pre-processing of schema for data values for all libraries. +// +// Returns the schema for the root library and enveloped schema for children libraries. +func (pp DataValuesSchemaPreProcessing) Apply() (*datavalues.Schema, []*datavalues.SchemaEnvelope, error) { + files := append([]*FileInLibrary{}, pp.schemaFiles...) + + // Ensure files are in assigned order so that overlays will be applied correctly. + SortFilesInLibrary(files) + + schema, libSchemas, err := pp.apply(files) + if err != nil { + errMsg := "Overlaying data values schema (in following order: %s): %s" + return nil, nil, fmt.Errorf(errMsg, pp.allFileDescs(files), err) + } + + return schema, libSchemas, nil +} + +func (pp DataValuesSchemaPreProcessing) apply(files []*FileInLibrary) (*datavalues.Schema, []*datavalues.SchemaEnvelope, error) { + allSchemas, err := pp.collectSchemaDocs(files) + if err != nil { + return nil, nil, err + } + + // merge all Schema documents into one + var schemaDoc *yamlmeta.Document + var childLibSchemas []*datavalues.SchemaEnvelope + for _, schema := range allSchemas { + if schema.IntendedForAnotherLibrary() { + childLibSchemas = append(childLibSchemas, schema) + continue + } + + if schemaDoc == nil { + schemaDoc = schema.Source() + } else { + schemaDoc, err = pp.overlay(schemaDoc, schema.Source()) + if err != nil { + return nil, nil, err + } + } + } + + var schema *datavalues.Schema + if schemaDoc == nil { + schema = datavalues.NewNullSchema() + } else { + schema, err = datavalues.NewSchema(schemaDoc) + if err != nil { + return nil, nil, err + } + } + + return schema, childLibSchemas, nil +} + +func (pp DataValuesSchemaPreProcessing) collectSchemaDocs(schemaFiles []*FileInLibrary) ([]*datavalues.SchemaEnvelope, error) { + var allSchema []*datavalues.SchemaEnvelope + for _, file := range schemaFiles { + docs, err := pp.extractSchemaDocs(file) + if err != nil { + return nil, fmt.Errorf("Templating file '%s': %s", file.File.RelativePath(), err) + } + + for _, d := range docs { + s, err := datavalues.NewSchemaEnvelope(d) + if err != nil { + return nil, err + } + allSchema = append(allSchema, s) + } + } + allSchema = append(allSchema, pp.schemaOverlays...) + return allSchema, nil +} + +func (pp DataValuesSchemaPreProcessing) extractSchemaDocs(schemaFile *FileInLibrary) ([]*yamlmeta.Document, error) { + libraryCtx := LibraryExecutionContext{Current: schemaFile.Library, Root: pp.rootLibrary} + + _, resultDocSet, err := pp.loader.EvalYAML(libraryCtx, schemaFile.File) + if err != nil { + return nil, err + } + + schemaDocs, nonSchemaDocs, err := DocExtractor{resultDocSet}.Extract(datavalues.AnnotationDataValuesSchema) + if err != nil { + return nil, err + } + + // For simplicity's sake, prohibit mixing data value schema documents with other kinds. + if len(nonSchemaDocs) > 0 { + for _, doc := range nonSchemaDocs { + if !doc.IsEmpty() { + errStr := "Expected schema file '%s' to only have schema documents" + return nil, fmt.Errorf(errStr, schemaFile.File.RelativePath()) + } + } + } + + return schemaDocs, nil +} + +func (pp DataValuesSchemaPreProcessing) allFileDescs(files []*FileInLibrary) string { + var result []string + for _, f := range files { + result = append(result, f.File.RelativePath()) + } + if len(pp.schemaOverlays) > 0 { + result = append(result, "additional data value schema") + } + return strings.Join(result, ", ") +} + +func (pp DataValuesSchemaPreProcessing) overlay(doc, overlay *yamlmeta.Document) (*yamlmeta.Document, error) { + op := yttoverlay.Op{ + Left: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{doc}}, + Right: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{overlay}}, + Thread: &starlark.Thread{Name: "data-values-schema-pre-processing"}, + + ExactMatch: true, + } + + result, err := op.Apply() + if err != nil { + return nil, err + } + + return result.(*yamlmeta.DocumentSet).Items[0], nil +} diff --git a/vendor/carvel.dev/ytt/pkg/workspace/datavalues/doc.go b/vendor/carvel.dev/ytt/pkg/workspace/datavalues/doc.go new file mode 100644 index 000000000..6b7e8fc21 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/datavalues/doc.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package datavalues integrates the schema and data values features into the +workspace, providing a means of "addressing" to specific libraries. +*/ +package datavalues diff --git a/vendor/carvel.dev/ytt/pkg/workspace/datavalues/envelope.go b/vendor/carvel.dev/ytt/pkg/workspace/datavalues/envelope.go new file mode 100644 index 000000000..0eb57a2fe --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/datavalues/envelope.go @@ -0,0 +1,162 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package datavalues + +import ( + "fmt" + "strings" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/workspace/ref" + "carvel.dev/ytt/pkg/yamlmeta" +) + +const ( + // AnnotationDataValues is the name of the annotation that marks a YAML document as a "Data Values" overlay. + AnnotationDataValues template.AnnotationName = "data/values" + + // AnnotationDataValuesSchema is the name of the annotation that marks a YAML document as a "Data Values Schema" + // overlay. + AnnotationDataValuesSchema template.AnnotationName = "data/values-schema" +) + +// Envelope wraps a YAML document containing Data Values along with addressing and usage bookkeeping — for which +// workspace.Library are these Data Values is intended. +type Envelope struct { + Doc *yamlmeta.Document + AfterLibMod bool + used bool + + originalLibRef []ref.LibraryRef + libRef []ref.LibraryRef +} + +// NewEnvelope generates a new Envelope from a YAML document containing Data Values, extracting "addressing" from any +// ref.LibraryRef annotated on the document. +func NewEnvelope(doc *yamlmeta.Document) (*Envelope, error) { + libRef, afterLibMod, err := parseDVLibAnnotations(ref.LibraryRefExtractor{}, doc) + if err != nil { + return nil, err + } + + return &Envelope{Doc: doc, AfterLibMod: afterLibMod, libRef: libRef, originalLibRef: libRef}, nil +} + +// NewEmptyEnvelope constructs a new Envelope that contains no Data Values. +func NewEmptyEnvelope() *Envelope { + return &Envelope{Doc: NewEmptyDataValuesDocument()} +} + +// NewEmptyDataValuesDocument produces a YAML document that contains an empty map: the expected result when no data +// values are specified. +func NewEmptyDataValuesDocument() *yamlmeta.Document { + return &yamlmeta.Document{ + Value: &yamlmeta.Map{}, + Position: filepos.NewUnknownPosition(), + } +} + +// NewEnvelopeWithLibRef constructs a new Envelope using the given library reference for "addressing" +// If libRefStr is empty string, then the Envelope has no "addressing" +func NewEnvelopeWithLibRef(doc *yamlmeta.Document, libRefStr string) (*Envelope, error) { + if len(libRefStr) > 0 { + return newEnvelopeWithLibRef(ref.LibraryRefExtractor{}, doc, libRefStr) + } + return NewEnvelope(doc) +} + +func newEnvelopeWithLibRef(libRefs ExtractLibRefs, doc *yamlmeta.Document, libRefStr string) (*Envelope, error) { + libRefsFromStr, err := libRefs.FromStr(libRefStr) + if err != nil { + return nil, err + } + + libRefsFromAnnotation, afterLibMod, err := parseDVLibAnnotations(libRefs, doc) + if err != nil { + return nil, err + } else if len(libRefsFromAnnotation) > 0 { + panic(fmt.Sprintf("Library was provided as arg as well as with %s annotation", ref.AnnotationLibraryRef)) + } + + return &Envelope{Doc: doc, AfterLibMod: afterLibMod, libRef: libRefsFromStr, originalLibRef: libRefsFromStr}, nil +} + +// IsUsed reports whether this Envelope of Data Values has been "delivered"/used. +func (dvd *Envelope) IsUsed() bool { return dvd.used } +func (dvd *Envelope) markUsed() { dvd.used = true } + +// Desc reports the destination library of this Envelope +func (dvd *Envelope) Desc() string { + // TODO: Update to output file location of annotation. If no annotation use doc position although these will always be used + var desc []string + for _, refPiece := range dvd.originalLibRef { + desc = append(desc, refPiece.AsString()) + } + return fmt.Sprintf("Data Value belonging to library '%s%s' on %s", ref.LibrarySep, + strings.Join(desc, ref.LibrarySep), dvd.Doc.Position.AsString()) +} + +// IntendedForAnotherLibrary indicates whether this Envelope is "addressed" to some other library. +func (dvd *Envelope) IntendedForAnotherLibrary() bool { return len(dvd.libRef) > 0 } + +// UsedInLibrary marks this Envelope as "delivered"/used if its destination is included in expectedRefPiece. +// +// If the Envelope should be used exactly in the specified library, returns a copy of this Envelope with no addressing +// (i.e. IntendedForAnotherLibrary() will indicate true). +// If the Envelope should be used in a _child_ of the specified library, returns a copy of this Envelope with +// the address of _that_ library. +// If the Envelope should **not** be used in the specified library or child, returns nil +func (dvd *Envelope) UsedInLibrary(expectedRefPiece ref.LibraryRef) *Envelope { + if len(dvd.libRef) == 0 { + dvd.markUsed() + return dvd.deepCopyUnused() + } + if !dvd.libRef[0].Matches(expectedRefPiece) { + return nil + } + dvd.markUsed() + childDV := dvd.deepCopyUnused() + childDV.libRef = childDV.libRef[1:] + return childDV +} + +func (dvd *Envelope) deepCopyUnused() *Envelope { + var copiedPieces []ref.LibraryRef + copiedPieces = append(copiedPieces, dvd.libRef...) + return &Envelope{Doc: dvd.Doc.DeepCopy(), AfterLibMod: dvd.AfterLibMod, + libRef: copiedPieces, originalLibRef: dvd.originalLibRef} +} + +func parseDVLibAnnotations(libRefs ExtractLibRefs, doc *yamlmeta.Document) ([]ref.LibraryRef, bool, error) { + var afterLibMod bool + anns := template.NewAnnotations(doc) + + libRef, err := libRefs.FromAnnotation(anns) + if err != nil { + return nil, false, err + } + + for _, kwarg := range anns.Kwargs(AnnotationDataValues) { + kwargName, err := core.NewStarlarkValue(kwarg[0]).AsString() + if err != nil { + return nil, false, err + } + + switch kwargName { + case "after_library_module": + afterLibMod, err = core.NewStarlarkValue(kwarg[1]).AsBool() + if err != nil { + return nil, false, err + } else if len(libRef) == 0 { + return nil, false, fmt.Errorf("Annotation %s: Expected kwarg 'after_library_module' to be used with %s annotation", + AnnotationDataValues, ref.AnnotationLibraryRef) + } + default: + return nil, false, fmt.Errorf("Unknown kwarg %s for annotation %s", kwargName, AnnotationDataValues) + } + } + return libRef, afterLibMod, nil +} diff --git a/vendor/carvel.dev/ytt/pkg/workspace/datavalues/schema.go b/vendor/carvel.dev/ytt/pkg/workspace/datavalues/schema.go new file mode 100644 index 000000000..4e38ea75f --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/datavalues/schema.go @@ -0,0 +1,176 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package datavalues + +import ( + "fmt" + "strings" + + "carvel.dev/ytt/pkg/schema" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/workspace/ref" + "carvel.dev/ytt/pkg/yamlmeta" +) + +// Schema is a definition of types and default values for Envelope. +type Schema struct { + Source *yamlmeta.Document + defaultDVs *yamlmeta.Document + DocType *schema.DocumentType +} + +// SchemaEnvelope is addressing and usage bookkeeping for a Schema — for which library this Schema is intended. +type SchemaEnvelope struct { + Doc *Schema + + used bool + originalLibRef []ref.LibraryRef + libRef []ref.LibraryRef +} + +// NewSchema calculates a Schema from a YAML document containing schema. +func NewSchema(doc *yamlmeta.Document) (*Schema, error) { + docType, err := schema.InferTypeFromValue(doc, doc.Position) + if err != nil { + return nil, err + } + + schemaDVs := docType.GetDefaultValue() + + return &Schema{ + Source: doc, + defaultDVs: schemaDVs.(*yamlmeta.Document), + DocType: docType.(*schema.DocumentType), + }, nil +} + +// NewSchemaEnvelope generates a new Schema wrapped in a SchemaEnvelope form a YAML document containing schema. +func NewSchemaEnvelope(doc *yamlmeta.Document) (*SchemaEnvelope, error) { + libRef, err := getSchemaLibRef(ref.LibraryRefExtractor{}, doc) + if err != nil { + return nil, err + } + + schema, err := NewSchema(doc) + if err != nil { + return nil, err + } + + return &SchemaEnvelope{ + Doc: schema, + originalLibRef: libRef, + libRef: libRef, + }, nil +} + +// NewNullSchema provides the "Null Object" value of Schema. This is used in the case where no schema was provided. +func NewNullSchema() *Schema { + return &Schema{ + Source: &yamlmeta.Document{}, + DocType: &schema.DocumentType{ + ValueType: &schema.AnyType{}}, + } +} + +// ExtractLibRefs constructs library references (ref.LibraryRef) from various sources. +type ExtractLibRefs interface { + FromStr(string) ([]ref.LibraryRef, error) + FromAnnotation(template.NodeAnnotations) ([]ref.LibraryRef, error) +} + +func getSchemaLibRef(libRefs ExtractLibRefs, doc *yamlmeta.Document) ([]ref.LibraryRef, error) { + anns := template.NewAnnotations(doc) + libRef, err := libRefs.FromAnnotation(anns) + if err != nil { + return nil, err + } + return libRef, nil +} + +// AssignType decorates `doc` with type metadata sourced from this Schema. +// If `doc` does not conform to the AST structure of this Schema, the returned TypeCheck contains the violations. +// No other type check is performed. +func (s *Schema) AssignType(doc *yamlmeta.Document) schema.TypeCheck { + return s.DocType.AssignTypeTo(doc) +} + +// DefaultDataValues returns a copy of the default values declared in this Schema. +func (s *Schema) DefaultDataValues() *yamlmeta.Document { + if s.defaultDVs == nil { + return nil + } + return s.defaultDVs.DeepCopy() +} + +// GetDocumentType returns a reference to the DocumentType that is the root of this Schema. +func (s *Schema) GetDocumentType() *schema.DocumentType { + return s.DocType +} + +// DeepCopy produces a complete copy of this Schema. +func (s *Schema) DeepCopy() *Schema { + return &Schema{ + Source: s.Source.DeepCopy(), + defaultDVs: s.defaultDVs.DeepCopy(), + DocType: s.DocType, + } +} + +// Source yields the original YAML document used to construct this SchemaEnvelope. +func (e *SchemaEnvelope) Source() *yamlmeta.Document { + return e.Doc.Source +} + +// Desc reports which library the contained Schema is intended. +func (e *SchemaEnvelope) Desc() string { + var desc []string + for _, refPiece := range e.originalLibRef { + desc = append(desc, refPiece.AsString()) + } + return fmt.Sprintf("Schema belonging to library '%s%s' on %s", "@", + strings.Join(desc, "@"), e.Source().Position.AsString()) +} + +// IsUsed reports whether or not the contained Schema was delivered/consumed. +func (e *SchemaEnvelope) IsUsed() bool { return e.used } + +// IntendedForAnotherLibrary indicates whether the contained Schema is addressed to another library. +func (e *SchemaEnvelope) IntendedForAnotherLibrary() bool { + return len(e.libRef) > 0 +} + +// UsedInLibrary marks this SchemaEnvelope as "delivered"/used if its destination is included in expectedRefPiece. +// +// If the SchemaEnvelope should be used exactly in the specified library, returns a copy of this SchemaEnvelope with no +// addressing and true. +// If the SchemaEnvelope should be used in a _child_ of the specified library, returns a copy of this SchemaEnvelope +// with the address of _that_ library and true. +// If the SchemaEnvelope should **not** be used in the specified library or child, returns nil and false. +func (e *SchemaEnvelope) UsedInLibrary(expectedRefPiece ref.LibraryRef) (*SchemaEnvelope, bool) { + if !e.IntendedForAnotherLibrary() { + e.markUsed() + + return e.deepCopyUnused(), true + } + + if !e.libRef[0].Matches(expectedRefPiece) { + return nil, false + } + e.markUsed() + childSchemaProcessing := e.deepCopyUnused() + childSchemaProcessing.libRef = childSchemaProcessing.libRef[1:] + return childSchemaProcessing, !childSchemaProcessing.IntendedForAnotherLibrary() +} + +func (e *SchemaEnvelope) markUsed() { e.used = true } + +func (e *SchemaEnvelope) deepCopyUnused() *SchemaEnvelope { + var copiedPieces []ref.LibraryRef + copiedPieces = append(copiedPieces, e.libRef...) + return &SchemaEnvelope{ + Doc: e.Doc.DeepCopy(), + originalLibRef: e.originalLibRef, + libRef: copiedPieces, + } +} diff --git a/vendor/carvel.dev/ytt/pkg/workspace/doc.go b/vendor/carvel.dev/ytt/pkg/workspace/doc.go new file mode 100644 index 000000000..98255202d --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/doc.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package workspace is home to primitives for loading and processing ytt artifacts +including the core four steps: pre-processing schema and data values, evaluating +templates, and post-processing overlays. +*/ +package workspace diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/doc_extractor.go b/vendor/carvel.dev/ytt/pkg/workspace/doc_extractor.go similarity index 62% rename from vendor/github.com/k14s/ytt/pkg/workspace/doc_extractor.go rename to vendor/carvel.dev/ytt/pkg/workspace/doc_extractor.go index 06fd5b8fe..5e062ef8f 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/doc_extractor.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/doc_extractor.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace @@ -6,14 +6,9 @@ package workspace import ( "fmt" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" -) - -const ( - AnnotationDataValues template.AnnotationName = "data/values" - AnnotationDataValuesSchema template.AnnotationName = "data/values-schema" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" ) type DocExtractor struct { @@ -48,17 +43,15 @@ func (v DocExtractor) extract(docSet *yamlmeta.DocumentSet, for _, comment := range doc.GetComments() { // TODO potentially use template.NewAnnotations(doc).Has(yttoverlay.AnnotationMatch) // however if doc was not processed by the template, it wont have any annotations set - meta, err := yamltemplate.NewTemplateMetaFromYAMLComment(comment, yamltemplate.MetasOpts{IgnoreUnknown: true}) + ann, err := yamltemplate.NewTemplateAnnotationFromYAMLComment(comment, doc.GetPosition(), template.MetaOpts{IgnoreUnknown: true}) if err != nil { return nil, nil, err } - for _, ann := range meta.Annotations { - if ann.Name == annName { - if hasMatchingAnn { - return nil, nil, fmt.Errorf("%s annotation may only be used once per YAML doc", annName) - } - hasMatchingAnn = true + if ann.Name == annName { + if hasMatchingAnn { + return nil, nil, fmt.Errorf("%s annotation may only be used once per document", annName) } + hasMatchingAnn = true } } @@ -79,19 +72,17 @@ func (v DocExtractor) checkNonDocs(val interface{}, annName template.AnnotationN } for _, comment := range node.GetComments() { - meta, err := yamltemplate.NewTemplateMetaFromYAMLComment(comment, yamltemplate.MetasOpts{IgnoreUnknown: true}) + ann, err := yamltemplate.NewTemplateAnnotationFromYAMLComment(comment, node.GetPosition(), template.MetaOpts{IgnoreUnknown: true}) if err != nil { return err } - for _, ann := range meta.Annotations { - if ann.Name == annName { - // TODO check for annotation emptiness - _, isDoc := node.(*yamlmeta.Document) - if !isDoc { - errMsg := "Expected YAML document to be annotated with %s but was %T" - return fmt.Errorf(errMsg, annName, node) - } + if ann.Name == annName { + // TODO check for annotation emptiness + _, isDoc := node.(*yamlmeta.Document) + if !isDoc { + errMsg := "Found @%s on %s (%s); only documents (---) can be annotated with @%s" + return fmt.Errorf(errMsg, annName, yamlmeta.TypeName(node), node.GetPosition().AsCompactString(), annName) } } } diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/library.go b/vendor/carvel.dev/ytt/pkg/workspace/library.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/workspace/library.go rename to vendor/carvel.dev/ytt/pkg/workspace/library.go index 1f48dd7d0..2b80b9127 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/library.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/library.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace @@ -10,7 +10,7 @@ import ( "sort" "strings" - "github.com/k14s/ytt/pkg/files" + "carvel.dev/ytt/pkg/files" ) const ( diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/library_execution.go b/vendor/carvel.dev/ytt/pkg/workspace/library_execution.go similarity index 55% rename from vendor/github.com/k14s/ytt/pkg/workspace/library_execution.go rename to vendor/carvel.dev/ytt/pkg/workspace/library_execution.go index b031c4c4c..bd2ba7672 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/library_execution.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/library_execution.go @@ -1,26 +1,30 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace import ( + "errors" "fmt" "strings" + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/validations" + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/yamlmeta" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" - "github.com/k14s/ytt/pkg/schema" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" - yttoverlay "github.com/k14s/ytt/pkg/yttlibrary/overlay" ) +// LibraryExecution is the total set of configuration and dependencies that are used to accomplish the execution of a +// Library. type LibraryExecution struct { - libraryCtx LibraryExecutionContext - ui ui.UI - templateLoaderOpts TemplateLoaderOpts - libraryExecFactory *LibraryExecutionFactory + libraryCtx LibraryExecutionContext + ui ui.UI + templateLoaderOpts TemplateLoaderOpts + libraryExecFactory *LibraryExecutionFactory + skipDataValuesValidation bool // when true, any validation rules present on data values are skipped } type EvalResult struct { @@ -34,126 +38,107 @@ type EvalExport struct { Symbols starlark.StringDict } -func NewLibraryExecution(libraryCtx LibraryExecutionContext, - ui ui.UI, templateLoaderOpts TemplateLoaderOpts, - libraryExecFactory *LibraryExecutionFactory) *LibraryExecution { +// NewLibraryExecution configures a new instance of a LibraryExecution. +func NewLibraryExecution(libraryCtx LibraryExecutionContext, ui ui.UI, templateLoaderOpts TemplateLoaderOpts, libraryExecFactory *LibraryExecutionFactory, skipDataValuesValidation bool) *LibraryExecution { return &LibraryExecution{ - libraryCtx: libraryCtx, - ui: ui, - templateLoaderOpts: templateLoaderOpts, - libraryExecFactory: libraryExecFactory, + libraryCtx: libraryCtx, + ui: ui, + templateLoaderOpts: templateLoaderOpts, + libraryExecFactory: libraryExecFactory, + skipDataValuesValidation: skipDataValuesValidation, } } -func (ll *LibraryExecution) Schemas(schemaOverlays []*schema.DocumentSchemaEnvelope) (Schema, []*schema.DocumentSchemaEnvelope, error) { - loader := NewTemplateLoader(NewEmptyDataValues(), nil, nil, ll.templateLoaderOpts, ll.libraryExecFactory, ll.ui) +// Schemas calculates the final schema for the Data Values in this library by combining/overlaying the schema file(s) +// in the library and the passed-in overlays. +// +// Returns this library's Schema and a slice of Schema intended for child libraries. +func (ll *LibraryExecution) Schemas(overlays []*datavalues.SchemaEnvelope) (*datavalues.Schema, []*datavalues.SchemaEnvelope, error) { + loader := NewTemplateLoader(datavalues.NewEmptyEnvelope(), nil, nil, ll.templateLoaderOpts, ll.libraryExecFactory, ll.ui) - schemaFiles, err := ll.schemaFiles(loader) + files, err := ll.schemaFiles(loader) if err != nil { return nil, nil, err } - documentSchemas, err := collectSchemaDocs(schemaFiles, loader) - if err != nil { - return nil, nil, err + spp := DataValuesSchemaPreProcessing{ + schemaFiles: files, + schemaOverlays: overlays, + loader: loader, + rootLibrary: ll.libraryCtx.Root, } - documentSchemas = append(documentSchemas, schemaOverlays...) - - var resultSchemasDoc *yamlmeta.Document - var childLibrarySchemas []*schema.DocumentSchemaEnvelope - for _, docSchema := range documentSchemas { - if docSchema.IntendedForAnotherLibrary() { - childLibrarySchemas = append(childLibrarySchemas, docSchema) - continue - } - if resultSchemasDoc == nil { - resultSchemasDoc = docSchema.Source() - } else { - resultSchemasDoc, err = ll.overlay(resultSchemasDoc, docSchema.Source()) - if err != nil { - return nil, nil, err - } - } - } - if resultSchemasDoc != nil { - currentLibrarySchema, err := schema.NewDocumentSchema(resultSchemasDoc) - if err != nil { - return nil, nil, err - } - return currentLibrarySchema, childLibrarySchemas, nil - } - return schema.NewNullSchema(), childLibrarySchemas, nil + return spp.Apply() } -func collectSchemaDocs(schemaFiles []*FileInLibrary, loader *TemplateLoader) ([]*schema.DocumentSchemaEnvelope, error) { - var documentSchemas []*schema.DocumentSchemaEnvelope - for _, file := range schemaFiles { - libraryCtx := LibraryExecutionContext{Current: file.Library, Root: NewRootLibrary(nil)} - - _, resultDocSet, err := loader.EvalYAML(libraryCtx, file.File) - if err != nil { - return nil, err - } +// Values calculates the final Data Values for this library by combining/overlaying defaults from the schema, the Data +// Values file(s) in the library, and the passed-in Data Values overlays. The final Data Values are validated using +// the validations annotated on a Data Value. +// +// Returns this library's Data Values and a collection of Data Values addressed to child libraries. +// Returns an error if the overlay operation fails or the result over an overlay fails a schema check. +func (ll *LibraryExecution) Values(valuesOverlays []*datavalues.Envelope, schema *datavalues.Schema) (*datavalues.Envelope, []*datavalues.Envelope, error) { + loader := NewTemplateLoader(datavalues.NewEmptyEnvelope(), nil, nil, ll.templateLoaderOpts, ll.libraryExecFactory, ll.ui) - docs, _, err := DocExtractor{resultDocSet}.Extract(AnnotationDataValuesSchema) - if err != nil { - return nil, err - } - for _, doc := range docs { - newSchema, err := schema.NewDocumentSchemaEnvelope(doc) - if err != nil { - return nil, err - } - documentSchemas = append(documentSchemas, newSchema) - } + valuesFiles, err := ll.valuesFiles(loader) + if err != nil { + return nil, nil, err } - return documentSchemas, nil -} - -func (ll *LibraryExecution) overlay(schema, overlay *yamlmeta.Document) (*yamlmeta.Document, error) { - op := yttoverlay.Op{ - Left: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{schema}}, - Right: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{overlay}}, - Thread: &starlark.Thread{Name: "schema-pre-processing"}, - ExactMatch: true, + dvpp := DataValuesPreProcessing{ + valuesFiles: valuesFiles, + valuesOverlays: valuesOverlays, + schema: schema, + loader: loader, + rootLibrary: ll.libraryCtx.Root, } - newLeft, err := op.Apply() + values, libValues, err := dvpp.Apply() if err != nil { - return nil, err + return nil, nil, err } - return newLeft.(*yamlmeta.DocumentSet).Items[0], nil + if !ll.skipDataValuesValidation { + err = ll.validateValues(values) + if err != nil { + return nil, nil, fmt.Errorf("Validating final data values:\n%s", err) + } + } + return values, libValues, err } -func (ll *LibraryExecution) Values(valuesOverlays []*DataValues, schema Schema) (*DataValues, []*DataValues, error) { - loader := NewTemplateLoader(NewEmptyDataValues(), nil, nil, ll.templateLoaderOpts, ll.libraryExecFactory, ll.ui) +// validateValues runs validations on Data Values for the current library. +// Validations are attached to data value and come from two sources: +// 1. @schema/validation annotations in a data values schema file. +// 2. @assert/validate annotations in a data values file. +// +// Returns an error if the arguments to an @assert/validate are invalid, +// otherwise, checks the Check for violations, and returns nil if there are no violations. +func (ll *LibraryExecution) validateValues(values *datavalues.Envelope) error { + err := validations.ProcessAssertValidateAnns(values.Doc) + if err != nil { + return err + } - valuesFiles, err := ll.valuesFiles(loader) + chk, err := validations.Run(values.Doc, "run-data-values-validations") if err != nil { - return nil, nil, err + return err } - dvpp := DataValuesPreProcessing{ - valuesFiles: valuesFiles, - valuesOverlays: valuesOverlays, - schema: schema, - loader: loader, - IgnoreUnknownComments: ll.templateLoaderOpts.IgnoreUnknownComments, + if chk.HasInvalidations() { + return errors.New(chk.ResultsAsString()) } - return dvpp.Apply() + return nil } func (ll *LibraryExecution) schemaFiles(loader *TemplateLoader) ([]*FileInLibrary, error) { - return ll.filesByAnnotation(AnnotationDataValuesSchema, loader) + return ll.filesByAnnotation(datavalues.AnnotationDataValuesSchema, loader) } func (ll *LibraryExecution) valuesFiles(loader *TemplateLoader) ([]*FileInLibrary, error) { - return ll.filesByAnnotation(AnnotationDataValues, loader) + return ll.filesByAnnotation(datavalues.AnnotationDataValues, loader) } @@ -182,7 +167,13 @@ func (ll *LibraryExecution) filesByAnnotation(annName template.AnnotationName, l return valuesFiles, nil } -func (ll *LibraryExecution) Eval(values *DataValues, libraryValues []*DataValues, librarySchemas []*schema.DocumentSchemaEnvelope) (*EvalResult, error) { +// Eval given the final data values (as the parameter values) runs this LibraryExecution, evaluating all templates in +// this library and then applying overlays over that result. +// +// Returns the final set of Documents and output files. +// Returns an error if any template fails to evaluate, any overlay fails to apply, or if one or more "Envelopes" were +// not delivered/used. +func (ll *LibraryExecution) Eval(values *datavalues.Envelope, libraryValues []*datavalues.Envelope, librarySchemas []*datavalues.SchemaEnvelope) (*EvalResult, error) { exports, docSets, outputFiles, err := ll.eval(values, libraryValues, librarySchemas) if err != nil { return nil, err @@ -215,7 +206,7 @@ func (ll *LibraryExecution) Eval(values *DataValues, libraryValues []*DataValues return result, nil } -func (ll *LibraryExecution) eval(values *DataValues, libraryValues []*DataValues, librarySchemas []*schema.DocumentSchemaEnvelope) ([]EvalExport, map[*FileInLibrary]*yamlmeta.DocumentSet, []files.OutputFile, error) { +func (ll *LibraryExecution) eval(values *datavalues.Envelope, libraryValues []*datavalues.Envelope, librarySchemas []*datavalues.SchemaEnvelope) ([]EvalExport, map[*FileInLibrary]*yamlmeta.DocumentSet, []files.OutputFile, error) { loader := NewTemplateLoader(values, libraryValues, librarySchemas, ll.templateLoaderOpts, ll.libraryExecFactory, ll.ui) @@ -304,7 +295,7 @@ func (*LibraryExecution) sortedOutputDocSets(outputDocSets map[*FileInLibrary]*y return files } -func (LibraryExecution) checkUnusedDVsOrSchemas(libraryValues []*DataValues, librarySchemas []*schema.DocumentSchemaEnvelope) error { +func (LibraryExecution) checkUnusedDVsOrSchemas(libraryValues []*datavalues.Envelope, librarySchemas []*datavalues.SchemaEnvelope) error { var unusedValuesDescs []string var unusedDocTypes []string numDVNotUsed := 0 diff --git a/vendor/carvel.dev/ytt/pkg/workspace/library_execution_factory.go b/vendor/carvel.dev/ytt/pkg/workspace/library_execution_factory.go new file mode 100644 index 000000000..18eb16448 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/library_execution_factory.go @@ -0,0 +1,48 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package workspace + +import ( + "carvel.dev/ytt/pkg/cmd/ui" +) + +// LibraryExecutionContext holds the total set of inputs that are involved in a LibraryExecution. +type LibraryExecutionContext struct { + Current *Library // the target library that will be executed/evaluated. + Root *Library // reference to the root library to support accessing "absolute path" loading of files. +} + +// LibraryExecutionFactory holds configuration for and produces instances of LibraryExecution's. +type LibraryExecutionFactory struct { + ui ui.UI + templateLoaderOpts TemplateLoaderOpts + + skipDataValuesValidation bool +} + +// NewLibraryExecutionFactory configures a new instance of a LibraryExecutionFactory. +func NewLibraryExecutionFactory(ui ui.UI, templateLoaderOpts TemplateLoaderOpts, skipDataValuesValidation bool) *LibraryExecutionFactory { + return &LibraryExecutionFactory{ui, templateLoaderOpts, skipDataValuesValidation} +} + +// WithTemplateLoaderOptsOverrides produces a new LibraryExecutionFactory identical to this one, except it configures +// its TemplateLoader with the merge of the supplied TemplateLoaderOpts over this factory's configuration. +func (f *LibraryExecutionFactory) WithTemplateLoaderOptsOverrides(overrides TemplateLoaderOptsOverrides) *LibraryExecutionFactory { + return NewLibraryExecutionFactory(f.ui, f.templateLoaderOpts.Merge(overrides), f.skipDataValuesValidation) +} + +// ThatSkipsDataValuesValidations produces a new LibraryExecutionFactory identical to this one, except it might also +// skip running validation rules over Data Values. +// +// If a LibraryExecutionFactory has already been configured to skip validations, calling this method with `true` has +// no effect. This stems from the assumption that the downstream user is the most informed whether validations ought to +// be run. +func (f *LibraryExecutionFactory) ThatSkipsDataValuesValidations(skipDataValuesValidation bool) *LibraryExecutionFactory { + return NewLibraryExecutionFactory(f.ui, f.templateLoaderOpts, f.skipDataValuesValidation || skipDataValuesValidation) +} + +// New produces a new instance of a LibraryExecution, set with the configuration and dependencies of this factory. +func (f *LibraryExecutionFactory) New(ctx LibraryExecutionContext) *LibraryExecution { + return NewLibraryExecution(ctx, f.ui, f.templateLoaderOpts, f, f.skipDataValuesValidation) +} diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/library_module.go b/vendor/carvel.dev/ytt/pkg/workspace/library_module.go similarity index 76% rename from vendor/github.com/k14s/ytt/pkg/workspace/library_module.go rename to vendor/carvel.dev/ytt/pkg/workspace/library_module.go index f9f4eca73..2fa07fb0d 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/library_module.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/library_module.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace @@ -7,30 +7,37 @@ import ( "fmt" "strings" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/workspace/ref" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" + "carvel.dev/ytt/pkg/yttlibrary/overlay" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/schema" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/workspace/ref" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" ) +// LibraryModule is the definition of the ytt-supplied Starlark module `@ytt:library` +// +// This module produces library instances (see Get()). The configuration is copied from the +// library execution to the new instance of a library module (see NewLibraryModule()) type LibraryModule struct { libraryCtx LibraryExecutionContext libraryExecutionFactory *LibraryExecutionFactory - libraryValues []*DataValues - librarySchemas []*schema.DocumentSchemaEnvelope + libraryValues []*datavalues.Envelope + librarySchemas []*datavalues.SchemaEnvelope } func NewLibraryModule(libraryCtx LibraryExecutionContext, libraryExecutionFactory *LibraryExecutionFactory, - libraryValues []*DataValues, librarySchemas []*schema.DocumentSchemaEnvelope) LibraryModule { + libraryValues []*datavalues.Envelope, librarySchemas []*datavalues.SchemaEnvelope) LibraryModule { return LibraryModule{libraryCtx, libraryExecutionFactory, libraryValues, librarySchemas} } +// AsModule defines the contents of the "@ytt:library" module. +// Produces an instance of the "@ytt:library" module suitable to be consumed by starlark.Thread.Load() func (b LibraryModule) AsModule() starlark.StringDict { return starlark.StringDict{ "library": &starlarkstruct.Module{ @@ -42,6 +49,7 @@ func (b LibraryModule) AsModule() starlark.StringDict { } } +// Get is a starlark.Builtin that, given the path to a private library, returns an instance of it as a libraryValue. func (b LibraryModule) Get(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { @@ -54,7 +62,7 @@ func (b LibraryModule) Get(thread *starlark.Thread, f *starlark.Builtin, return starlark.None, err } - libAlias, tplLoaderOptsOverrides, err := b.getOpts(kwargs) + libAlias, tplLoaderOptsOverrides, wantsToSkipDVValidations, err := b.getOpts(kwargs) if err != nil { return starlark.None, err } @@ -70,66 +78,78 @@ func (b LibraryModule) Get(thread *starlark.Thread, f *starlark.Builtin, } // copy over library values - dataValuess := append([]*DataValues{}, b.libraryValues...) + dataValuess := append([]*datavalues.Envelope{}, b.libraryValues...) libraryCtx := LibraryExecutionContext{Current: foundLib, Root: foundLib} return (&libraryValue{libPath, libAlias, dataValuess, b.librarySchemas, libraryCtx, - b.libraryExecutionFactory.WithTemplateLoaderOptsOverrides(tplLoaderOptsOverrides), + b.libraryExecutionFactory. + WithTemplateLoaderOptsOverrides(tplLoaderOptsOverrides). + ThatSkipsDataValuesValidations(wantsToSkipDVValidations), }).AsStarlarkValue(), nil } -func (b LibraryModule) getOpts(kwargs []starlark.Tuple) (string, TemplateLoaderOptsOverrides, error) { +func (b LibraryModule) getOpts(kwargs []starlark.Tuple) (string, TemplateLoaderOptsOverrides, bool, error) { var alias string var overrides TemplateLoaderOptsOverrides + var skipDataValuesValidation = false for _, kwarg := range kwargs { name, err := core.NewStarlarkValue(kwarg[0]).AsString() if err != nil { - return "", overrides, err + return "", overrides, false, err } switch name { case "alias": val, err := core.NewStarlarkValue(kwarg[1]).AsString() if err != nil { - return "", overrides, err + return "", overrides, false, err } alias = val case "ignore_unknown_comments": result, err := core.NewStarlarkValue(kwarg[1]).AsBool() if err != nil { - return "", overrides, err + return "", overrides, false, err } overrides.IgnoreUnknownComments = &result case "implicit_map_key_overrides": result, err := core.NewStarlarkValue(kwarg[1]).AsBool() if err != nil { - return "", overrides, err + return "", overrides, false, err } overrides.ImplicitMapKeyOverrides = &result case "strict": result, err := core.NewStarlarkValue(kwarg[1]).AsBool() if err != nil { - return "", overrides, err + return "", overrides, false, err } overrides.StrictYAML = &result + case "dangerous_data_values_disable_validation": + result, err := core.NewStarlarkValue(kwarg[1]).AsBool() + if err != nil { + return "", overrides, false, err + } + skipDataValuesValidation = result + default: - return "", overrides, fmt.Errorf("Unexpected kwarg '%s'", name) + return "", overrides, false, fmt.Errorf("Unexpected kwarg '%s'", name) } } - return alias, overrides, nil + return alias, overrides, skipDataValuesValidation, nil } +// libraryValue is an instance of a private library. +// Instances are immutable. type libraryValue struct { path string alias string - dataValuess []*DataValues - schemas []*schema.DocumentSchemaEnvelope + dataValuess []*datavalues.Envelope + schemas []*datavalues.SchemaEnvelope libraryCtx LibraryExecutionContext libraryExecutionFactory *LibraryExecutionFactory @@ -165,16 +185,35 @@ func (l *libraryValue) WithDataValues(thread *starlark.Thread, f *starlark.Built return starlark.None, err } - valsYAML, err := NewDataValues(&yamlmeta.Document{ + allowedKWArgs := map[string]struct{}{ + "plain": {}, + } + if err := core.CheckArgNames(kwargs, allowedKWArgs); err != nil { + return starlark.None, err + } + + usePlainMerge, err := core.BoolArg(kwargs, "plain", false) + if err != nil { + return starlark.None, err + } + + dvDoc := &yamlmeta.Document{ Value: yamlmeta.NewASTFromInterfaceWithNoPosition(dataValues), Position: filepos.NewUnknownPosition(), - }) + } + + if usePlainMerge { + err = overlay.AnnotateForPlainMerge(dvDoc) + if err != nil { + return starlark.None, err + } + } + valsYAML, err := datavalues.NewEnvelope(dvDoc) if err != nil { return starlark.None, err } - // copy over library values - newDataValuess := append([]*DataValues{}, l.dataValuess...) + newDataValuess := append([]*datavalues.Envelope{}, l.dataValuess...) newDataValuess = append(newDataValuess, valsYAML) libVal := &libraryValue{l.path, l.alias, newDataValuess, l.schemas, l.libraryCtx, l.libraryExecutionFactory} @@ -194,7 +233,7 @@ func (l *libraryValue) WithDataValuesSchema(thread *starlark.Thread, f *starlark return starlark.None, err } - newDocSchema, err := schema.NewDocumentSchemaEnvelope(&yamlmeta.Document{ + newDocSchema, err := datavalues.NewSchemaEnvelope(&yamlmeta.Document{ Value: yamlmeta.NewASTFromInterface(libSchema), Position: filepos.NewUnknownPosition(), }) @@ -202,7 +241,7 @@ func (l *libraryValue) WithDataValuesSchema(thread *starlark.Thread, f *starlark return starlark.None, err } - newLibSchemas := append([]*schema.DocumentSchemaEnvelope{}, l.schemas...) + newLibSchemas := append([]*datavalues.SchemaEnvelope{}, l.schemas...) newLibSchemas = append(newLibSchemas, newDocSchema) libVal := &libraryValue{l.path, l.alias, l.dataValuess, newLibSchemas, l.libraryCtx, l.libraryExecutionFactory} @@ -348,8 +387,8 @@ func (l *libraryValue) exportArgs(args starlark.Tuple, kwargs []starlark.Tuple) return symbolName, locationPath, nil } -func (l *libraryValue) librarySchemas(ll *LibraryExecution) (Schema, []*schema.DocumentSchemaEnvelope, error) { - var schemasForCurrentLib, schemasForChildLib []*schema.DocumentSchemaEnvelope +func (l *libraryValue) librarySchemas(ll *LibraryExecution) (*datavalues.Schema, []*datavalues.SchemaEnvelope, error) { + var schemasForCurrentLib, schemasForChildLib []*datavalues.SchemaEnvelope for _, docSchema := range l.schemas { matchingSchema, usedInCurrLibrary := docSchema.UsedInLibrary(ref.LibraryRef{Path: l.path, Alias: l.alias}) @@ -369,8 +408,8 @@ func (l *libraryValue) librarySchemas(ll *LibraryExecution) (Schema, []*schema.D return schema, foundChildSchemas, nil } -func (l *libraryValue) libraryValues(ll *LibraryExecution, schema Schema) (*DataValues, []*DataValues, error) { - var dvss, afterLibModDVss, childDVss []*DataValues +func (l *libraryValue) libraryValues(ll *LibraryExecution, schema *datavalues.Schema) (*datavalues.Envelope, []*datavalues.Envelope, error) { + var dvss, afterLibModDVss, childDVss []*datavalues.Envelope for _, dv := range l.dataValuess { matchingDVs := dv.UsedInLibrary(ref.LibraryRef{Path: l.path, Alias: l.alias}) if matchingDVs != nil { diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/overlay_post_processing.go b/vendor/carvel.dev/ytt/pkg/workspace/overlay_post_processing.go similarity index 91% rename from vendor/github.com/k14s/ytt/pkg/workspace/overlay_post_processing.go rename to vendor/carvel.dev/ytt/pkg/workspace/overlay_post_processing.go index 7024335a9..518125600 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/overlay_post_processing.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/overlay_post_processing.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace @@ -7,10 +7,10 @@ import ( "fmt" "strings" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" + yttoverlay "carvel.dev/ytt/pkg/yttlibrary/overlay" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" - yttoverlay "github.com/k14s/ytt/pkg/yttlibrary/overlay" ) type OverlayPostProcessing struct { @@ -75,7 +75,7 @@ func (o OverlayPostProcessing) Apply() (map[*FileInLibrary]*yamlmeta.DocumentSet if file, ok := docSetToFilesMapping[docSet]; ok { result[file] = docSet } else { - return nil, fmt.Errorf("Expected to find file for docset") + return nil, fmt.Errorf("Expected to find file for document set") } } diff --git a/vendor/carvel.dev/ytt/pkg/workspace/ref/doc.go b/vendor/carvel.dev/ytt/pkg/workspace/ref/doc.go new file mode 100644 index 000000000..f5dbc5b02 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/workspace/ref/doc.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package ref provides the general-purpose ability to mark a document as targeted +for specific library. +*/ +package ref diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/ref/library_ref.go b/vendor/carvel.dev/ytt/pkg/workspace/ref/library_ref.go similarity index 88% rename from vendor/github.com/k14s/ytt/pkg/workspace/ref/library_ref.go rename to vendor/carvel.dev/ytt/pkg/workspace/ref/library_ref.go index 1ed09563b..d726e25f8 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/ref/library_ref.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/ref/library_ref.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package ref @@ -7,14 +7,14 @@ import ( "fmt" "strings" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/template/core" ) const ( AnnotationLibraryRef = "library/ref" - librarySep = "@" + LibrarySep = "@" libraryAliasIndicator = "~" ) @@ -74,12 +74,12 @@ func (n LibraryRefExtractor) FromStr(libRefStr string) ([]LibraryRef, error) { return nil, fmt.Errorf("Expected library ref to not be empty") } - if !strings.HasPrefix(libRefStr, librarySep) { - return nil, fmt.Errorf("Expected library ref to start with '%s'", librarySep) + if !strings.HasPrefix(libRefStr, LibrarySep) { + return nil, fmt.Errorf("Expected library ref to start with '%s'", LibrarySep) } var result []LibraryRef - for _, refPiece := range strings.Split(libRefStr, librarySep)[1:] { + for _, refPiece := range strings.Split(libRefStr, LibrarySep)[1:] { pathAndAlias := strings.Split(refPiece, libraryAliasIndicator) switch l := len(pathAndAlias); { case l == 1: diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/template_loader.go b/vendor/carvel.dev/ytt/pkg/workspace/template_loader.go similarity index 83% rename from vendor/github.com/k14s/ytt/pkg/workspace/template_loader.go rename to vendor/carvel.dev/ytt/pkg/workspace/template_loader.go index ea2955dfc..ef6d7a26a 100644 --- a/vendor/github.com/k14s/ytt/pkg/workspace/template_loader.go +++ b/vendor/carvel.dev/ytt/pkg/workspace/template_loader.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package workspace @@ -7,41 +7,44 @@ import ( "fmt" "strings" + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/files" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/texttemplate" + "carvel.dev/ytt/pkg/workspace/datavalues" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" + "carvel.dev/ytt/pkg/yttlibrary" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" - "github.com/k14s/ytt/pkg/schema" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/texttemplate" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" - "github.com/k14s/ytt/pkg/yttlibrary" ) type TemplateLoader struct { ui ui.UI - values *DataValues - libraryValuess []*DataValues - librarySchemas []*schema.DocumentSchemaEnvelope + values *datavalues.Envelope + libraryValuess []*datavalues.Envelope + librarySchemas []*datavalues.SchemaEnvelope opts TemplateLoaderOpts compiledTemplates map[string]*template.CompiledTemplate libraryExecFactory *LibraryExecutionFactory } +// TemplateLoaderOpts holds configuration options that adjust how each individual template is executed/evaluated. type TemplateLoaderOpts struct { IgnoreUnknownComments bool ImplicitMapKeyOverrides bool StrictYAML bool - SchemaEnabled bool } +// TemplateLoaderOptsOverrides hold potential overriding values to be merged over a TemplateLoaderOpts. +// Only non-null values are merged. type TemplateLoaderOptsOverrides struct { IgnoreUnknownComments *bool ImplicitMapKeyOverrides *bool StrictYAML *bool } -func NewTemplateLoader(values *DataValues, libraryValuess []*DataValues, librarySchemas []*schema.DocumentSchemaEnvelope, opts TemplateLoaderOpts, libraryExecFactory *LibraryExecutionFactory, ui ui.UI) *TemplateLoader { +// NewTemplateLoader instantiates a new TemplateLoader. +func NewTemplateLoader(values *datavalues.Envelope, libraryValuess []*datavalues.Envelope, librarySchemas []*datavalues.SchemaEnvelope, opts TemplateLoaderOpts, libraryExecFactory *LibraryExecutionFactory, ui ui.UI) *TemplateLoader { if values == nil { panic("Expected values to be non-nil") @@ -58,12 +61,11 @@ func NewTemplateLoader(values *DataValues, libraryValuess []*DataValues, library } } -func (l *TemplateLoader) FindCompiledTemplate(path string) (*template.CompiledTemplate, error) { - ct, found := l.compiledTemplates[path] - if !found { - return nil, fmt.Errorf("Expected to find '%s' compiled template", path) - } - return ct, nil +// FindCompiledTemplate returns the template.CompiledTemplate that was produced from the file at "path". +// +// If no such template exists, returns nil. +func (l *TemplateLoader) FindCompiledTemplate(path string) *template.CompiledTemplate { + return l.compiledTemplates[path] } func (l *TemplateLoader) Load(thread *starlark.Thread, module string) (starlark.StringDict, error) { @@ -147,25 +149,38 @@ func (l *TemplateLoader) EvalPlainYAML(file *files.File) (*yamlmeta.DocumentSet, docSet, err := yamlmeta.NewDocumentSetFromBytes(fileBs, docSetOpts) if err != nil { - return nil, fmt.Errorf("Unmarshaling YAML template '%s': %s", file.RelativePath(), err) + return nil, fmt.Errorf("Unmarshaling YAML template '%s': %s", file.Description(), err) } return docSet, nil } +// EvalYAML parses the file into a Node AST, then compiles that Node tree into a starlark program. +// +// Returns the templated file by evaluating the compiled starlark program. func (l *TemplateLoader) EvalYAML(libraryCtx LibraryExecutionContext, file *files.File) (starlark.StringDict, *yamlmeta.DocumentSet, error) { docSet, err := l.EvalPlainYAML(file) if err != nil { return nil, nil, err } - l.ui.Debugf("### ast\n") - docSet.Print(l.ui.DebugWriter()) + l.ui.Debugf("### ast ") + // is this plain YAML? if !file.IsTemplate() && !file.IsLibrary() || !yamltemplate.HasTemplating(docSet) { + // YAML spec requires map keys to be unique. + // Tools retain just the last instance: each subsequent map item overrides the value of any previous. + docSet.OverrideMapKeys() + + l.ui.Debugf("(plain)\n") + docSet.Print(l.ui.DebugWriter()) + return nil, docSet, nil } + l.ui.Debugf("(templated)\n") + docSet.Print(l.ui.DebugWriter()) + tplOpts := yamltemplate.TemplateOpts{ IgnoreUnknownComments: l.opts.IgnoreUnknownComments, ImplicitMapKeyOverrides: l.opts.ImplicitMapKeyOverrides, @@ -181,7 +196,7 @@ func (l *TemplateLoader) EvalYAML(libraryCtx LibraryExecutionContext, file *file yttLibrary := yttlibrary.NewAPI(compiledTemplate.TplReplaceNode, yttlibrary.NewDataModule(l.values.Doc, DataLoader{libraryCtx}), - NewLibraryModule(libraryCtx, l.libraryExecFactory, l.libraryValuess, l.librarySchemas).AsModule()) + NewLibraryModule(libraryCtx, l.libraryExecFactory, l.libraryValuess, l.librarySchemas).AsModule(), l.ui) thread := l.newThread(libraryCtx, yttLibrary, file) @@ -223,7 +238,7 @@ func (l *TemplateLoader) EvalText(libraryCtx LibraryExecutionContext, file *file yttLibrary := yttlibrary.NewAPI(compiledTemplate.TplReplaceNode, yttlibrary.NewDataModule(l.values.Doc, DataLoader{libraryCtx}), - NewLibraryModule(libraryCtx, l.libraryExecFactory, l.libraryValuess, l.librarySchemas).AsModule()) + NewLibraryModule(libraryCtx, l.libraryExecFactory, l.libraryValuess, l.librarySchemas).AsModule(), l.ui) thread := l.newThread(libraryCtx, yttLibrary, file) @@ -253,7 +268,7 @@ func (l *TemplateLoader) EvalStarlark(libraryCtx LibraryExecutionContext, file * yttLibrary := yttlibrary.NewAPI(compiledTemplate.TplReplaceNode, yttlibrary.NewDataModule(l.values.Doc, DataLoader{libraryCtx}), - NewLibraryModule(libraryCtx, l.libraryExecFactory, l.libraryValuess, l.librarySchemas).AsModule()) + NewLibraryModule(libraryCtx, l.libraryExecFactory, l.libraryValuess, l.librarySchemas).AsModule(), l.ui) thread := l.newThread(libraryCtx, yttLibrary, file) diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/ast.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/ast.go similarity index 80% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/ast.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/ast.go index 65bb611da..dc60d6bd2 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/ast.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/ast.go @@ -1,10 +1,10 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta import ( - "github.com/k14s/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/filepos" ) type Node interface { @@ -17,26 +17,22 @@ type Node interface { ResetValue() GetComments() []*Comment + SetComments([]*Comment) addComments(*Comment) + GetMeta(name string) interface{} + SetMeta(name string, data interface{}) GetAnnotations() interface{} SetAnnotations(interface{}) DeepCopyAsInterface() interface{} DeepCopyAsNode() Node - Check() TypeCheck - sealed() // limit the concrete types of Node to map directly only to types allowed in YAML spec. -} -type ValueHoldingNode interface { - Node - Val() interface{} } var _ = []Node{&DocumentSet{}, &Map{}, &Array{}} -var _ = []ValueHoldingNode{&Document{}, &MapItem{}, &ArrayItem{}} type DocumentSet struct { Comments []*Comment @@ -45,62 +41,58 @@ type DocumentSet struct { Items []*Document Position *filepos.Position + meta map[string]interface{} annotations interface{} originalBytes *[]byte } type Document struct { - Type Type Comments []*Comment Value interface{} Position *filepos.Position + meta map[string]interface{} annotations interface{} injected bool // indicates that Document was not present in the parsed content } type Map struct { - Type Type Comments []*Comment Items []*MapItem Position *filepos.Position + meta map[string]interface{} annotations interface{} } type MapItem struct { - Type Type Comments []*Comment Key interface{} Value interface{} Position *filepos.Position + meta map[string]interface{} annotations interface{} } type Array struct { - Type Type Comments []*Comment Items []*ArrayItem Position *filepos.Position + meta map[string]interface{} annotations interface{} } type ArrayItem struct { - Type Type Comments []*Comment Value interface{} Position *filepos.Position + meta map[string]interface{} annotations interface{} } -type Scalar struct { - Position *filepos.Position - Value interface{} -} - type Comment struct { Data string Position *filepos.Position diff --git a/vendor/carvel.dev/ytt/pkg/yamlmeta/construct.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/construct.go new file mode 100644 index 000000000..0980408fa --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/construct.go @@ -0,0 +1,150 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yamlmeta + +import "carvel.dev/ytt/pkg/filepos" + +// NewDocumentSet creates a new DocumentSet instance based on the given prototype +func NewDocumentSet(val *DocumentSetProto) *DocumentSet { + newDocSet := &DocumentSet{ + Comments: NewComments(val.Comments), + Position: val.Position, + } + for _, item := range val.Items { + newDocSet.Items = append(newDocSet.Items, NewDocument(item)) + } + return newDocSet +} + +// NewDocument creates a new Document instance based on the given prototype +func NewDocument(val *DocumentProto) *Document { + return &Document{ + Comments: NewComments(val.Comments), + Value: NewValue(val.Value), + Position: val.Position, + } +} + +// NewMap creates a new Map instance based on the given prototype +func NewMap(val *MapProto) *Map { + newMap := &Map{ + Comments: NewComments(val.Comments), + Position: val.Position, + } + for _, item := range val.Items { + newMap.Items = append(newMap.Items, NewMapItem(item)) + } + return newMap +} + +// NewMapItem creates a new MapItem instance based on the given prototype +func NewMapItem(val *MapItemProto) *MapItem { + return &MapItem{ + Comments: NewComments(val.Comments), + Key: val.Key, + Value: NewValue(val.Value), + Position: val.Position, + } +} + +// NewArray creates a new Array instance based on the given prototype +func NewArray(val *ArrayProto) *Array { + newArray := &Array{ + Comments: NewComments(val.Comments), + Position: val.Position, + } + for _, item := range val.Items { + newArray.Items = append(newArray.Items, NewArrayItem(item)) + } + return newArray +} + +// NewArrayItem creates a new ArrayItem instance based on the given prototype +func NewArrayItem(val *ArrayItemProto) *ArrayItem { + return &ArrayItem{ + Comments: NewComments(val.Comments), + Value: NewValue(val.Value), + Position: val.Position, + } +} + +// NewComments creates a new slice of Comment based on the given prototype +func NewComments(val []*CommentProto) []*Comment { + newComments := []*Comment{} + for _, comment := range val { + newComments = append(newComments, NewComment(comment)) + } + return newComments +} + +// NewComment creates a new Comment based on the given prototype +func NewComment(val *CommentProto) *Comment { + return &Comment{ + Data: val.Data, + Position: val.Position, + } +} + +// NewValue creates a new Document, Map, Array, or scalar, depending on the type of the given prototype +func NewValue(val interface{}) interface{} { + switch typedVal := val.(type) { + case *DocumentProto: + return NewDocument(typedVal) + case *MapProto: + return NewMap(typedVal) + case *ArrayProto: + return NewArray(typedVal) + default: + return val + } +} + +// DocumentSetProto is a prototype for a DocumentSet +type DocumentSetProto struct { + Items []*DocumentProto + Comments []*CommentProto + Position *filepos.Position +} + +// DocumentProto is a prototype for a Document +type DocumentProto struct { + Value interface{} + Comments []*CommentProto + Position *filepos.Position +} + +// MapProto is a prototype for a Map +type MapProto struct { + Items []*MapItemProto + Comments []*CommentProto + Position *filepos.Position +} + +// MapItemProto is a prototype for a MapItem +type MapItemProto struct { + Key interface{} + Value interface{} + Comments []*CommentProto + Position *filepos.Position +} + +// ArrayProto is a prototype for an Array +type ArrayProto struct { + Items []*ArrayItemProto + Comments []*CommentProto + Position *filepos.Position +} + +// ArrayItemProto is a prototype for an ArrayItem +type ArrayItemProto struct { + Value interface{} + Comments []*CommentProto + Position *filepos.Position +} + +// CommentProto is a prototype for a Comment +type CommentProto struct { + Data string + Position *filepos.Position +} diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/convert.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/convert.go similarity index 95% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/convert.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/convert.go index 93c59f450..1d58551c7 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/convert.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/convert.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -6,9 +6,9 @@ package yamlmeta import ( "fmt" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/orderedmap" - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" ) func NewASTFromInterface(val interface{}) interface{} { @@ -59,11 +59,8 @@ func convertToLowYAML(val interface{}) interface{} { func convertToGo(val interface{}) interface{} { switch typedVal := val.(type) { - case *DocumentSet: - panic("Unexpected docset value within document") - - case *Document: - panic("Unexpected document within document") + case *DocumentSet, *Document: + panic(fmt.Sprintf("Unexpected %T value within %T", val, &Document{})) case *Map: result := orderedmap.NewMap() @@ -149,7 +146,7 @@ func convertToAST(val interface{}, defaultPosition *filepos.Position) interface{ return typedVal case []interface{}: - result := &Array{} + result := &Array{Position: defaultPosition} for _, item := range typedVal { result.Items = append(result.Items, &ArrayItem{ Value: convertToAST(item, defaultPosition), diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/deep_copy.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/deep_copy.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/deep_copy.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/deep_copy.go index 2e606a7cd..84e51c63f 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/deep_copy.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/deep_copy.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta diff --git a/vendor/carvel.dev/ytt/pkg/yamlmeta/doc.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/doc.go new file mode 100644 index 000000000..4ad7ca07a --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/doc.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package yamlmeta parses YAML streams into a data structure (tree of +yamlmeta.Node's) on which comments and metadata can be attached. +*/ +package yamlmeta diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/document.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/document.go similarity index 87% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/document.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/document.go index e2f96ca67..74e2bea1a 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/document.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/document.go @@ -1,10 +1,10 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta import ( - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" ) func (d *Document) IsEmpty() bool { diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/document_set.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/document_set.go similarity index 83% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/document_set.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/document_set.go index 36b5fd4c8..7e494cc7e 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/document_set.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/document_set.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -60,3 +60,11 @@ func (ds *DocumentSet) AsBytesWithPrinter(printerFunc func(io.Writer) DocumentPr return buf.Bytes(), nil } + +// OverrideMapKeys within any contained Map, where there is more than one MapItem with the same key, delete all but the last. +func (ds *DocumentSet) OverrideMapKeys() { + err := Walk(ds, &overrideMapKeys{}) + if err != nil { + panic(err) + } +} diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/file_position_printer.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/file_position_printer.go similarity index 96% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/file_position_printer.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/file_position_printer.go index b7dcb58ed..ae00c143c 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/file_position_printer.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/file_position_printer.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -9,8 +9,8 @@ import ( "io" "strings" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" ) type FilePositionPrinter struct { diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/.travis.yml b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/.travis.yml similarity index 100% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/.travis.yml rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/.travis.yml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE similarity index 100% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE.libyaml b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE.libyaml similarity index 100% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE.libyaml rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/LICENSE.libyaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/NOTICE b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/NOTICE similarity index 100% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/NOTICE rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/NOTICE diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/README.md b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/README.md similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/README.md rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/README.md index 94f52272d..a25de6738 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/README.md +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/README.md @@ -55,7 +55,7 @@ import ( "fmt" "log" - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" ) var data = ` diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/apic.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/apic.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/apic.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/apic.go index cbb273967..ac6212a8f 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/apic.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/apic.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/decode.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/decode.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/decode.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/decode.go index 932ac61d8..26a74b3e5 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/decode.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/decode.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/emitterc.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/emitterc.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/emitterc.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/emitterc.go index 587b77eef..aa61e58ea 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/emitterc.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/emitterc.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/encode.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/encode.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/encode.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/encode.go index a01a0e9c9..073fc2bf0 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/encode.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/encode.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/parserc.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/parserc.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/parserc.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/parserc.go index 684880a05..704072d4f 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/parserc.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/parserc.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/readerc.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/readerc.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/readerc.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/readerc.go index eb3e1d0c0..09b11591e 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/readerc.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/readerc.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/resolve.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/resolve.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/resolve.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/resolve.go index 91ba4c888..3a7631697 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/resolve.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/resolve.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml @@ -84,7 +84,7 @@ func resolvableTag(tag string) bool { return false } -var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`) +var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) func resolve(tag string, in string) (rtag string, out interface{}) { if !resolvableTag(tag) { diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/scannerc.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/scannerc.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/scannerc.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/scannerc.go index 8662b99d3..f14e86329 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/scannerc.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/scannerc.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml @@ -78,7 +78,7 @@ import ( // %TAG !yaml! tag:yaml.org,2002: // --- // -// The correspoding sequence of tokens: +// The corresponding sequence of tokens: // // STREAM-START(utf-8) // VERSION-DIRECTIVE(1,1) @@ -1233,7 +1233,7 @@ func yamlParserFetchKey(parser *yamlParserT) bool { // In the block context, additional checks are required. if parser.flowLevel == 0 { - // Check if we are allowed to start a new key (not nessesary simple). + // Check if we are allowed to start a new key (not necessary simple). if !parser.simpleKeyAllowed { return yamlParserSetScannerError(parser, "", parser.mark, "mapping keys are not allowed in this context") diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/sorter.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/sorter.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/sorter.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/sorter.go index 25a1c25d8..66e067c98 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/sorter.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/sorter.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/strict_scalar_resolve.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/strict_scalar_resolve.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/strict_scalar_resolve.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/strict_scalar_resolve.go index 30e820293..d62df147c 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/strict_scalar_resolve.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/strict_scalar_resolve.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/writerc.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/writerc.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/writerc.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/writerc.go index 1decf0f0f..6ef426dab 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/writerc.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/writerc.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yaml.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yaml.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yaml.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yaml.go index 15202a6c2..85d8dca78 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yaml.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yaml.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 // Package yaml implements YAML support for the Go language. @@ -104,7 +104,7 @@ func UnmarshalWithComments(in []byte, out interface{}) ([]Comment, error) { return unmarshal(in, out, true) } -// A Decorder reads and decodes YAML values from an input stream. +// Decoder reads and decodes YAML values from an input stream. type Decoder struct { strict bool useMapSlice bool diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yamlh.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yamlh.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yamlh.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yamlh.go index 055cdee9f..32005667c 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yamlh.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yamlh.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml @@ -726,7 +726,7 @@ type yamlEmitterT struct { scalarData struct { value []byte // The scalar value. multiline bool // Does the scalar contain line breaks? - flowPlainAllowed bool // Can the scalar be expessed in the flow plain style? + flowPlainAllowed bool // Can the scalar be expressed in the flow plain style? blockPlainAllowed bool // Can the scalar be expressed in the block plain style? singleQuotedAllowed bool // Can the scalar be expressed in the single quoted style? blockAllowed bool // Can the scalar be expressed in the literal or folded styles? diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yamlprivateh.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yamlprivateh.go similarity index 99% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yamlprivateh.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yamlprivateh.go index c14d63baa..df9da677a 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2/yamlprivateh.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2/yamlprivateh.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yaml diff --git a/vendor/carvel.dev/ytt/pkg/yamlmeta/map_key_overrides.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/map_key_overrides.go new file mode 100644 index 000000000..8e123e199 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/map_key_overrides.go @@ -0,0 +1,32 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yamlmeta + +import ( + "carvel.dev/ytt/pkg/orderedmap" +) + +type overrideMapKeys struct{} + +// Visit if `node` is a Map, among its MapItem's that have duplicate keys, removes all but the last. +// This visitor always returns `nil` +func (r *overrideMapKeys) Visit(node Node) error { + mapNode, isMap := node.(*Map) + if !isMap { + return nil + } + + lastItems := orderedmap.NewMap() + for _, item := range mapNode.Items { + lastItems.Set(item.Key, item) + } + + var newItems []*MapItem + lastItems.Iterate(func(_, value interface{}) { + newItems = append(newItems, value.(*MapItem)) + }) + mapNode.Items = newItems + + return nil +} diff --git a/vendor/carvel.dev/ytt/pkg/yamlmeta/node.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/node.go new file mode 100644 index 000000000..a78c4a9e2 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/node.go @@ -0,0 +1,398 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yamlmeta + +import ( + "encoding/json" + "fmt" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" +) + +// TypeName returns the user-friendly name of the type of `val` +func TypeName(val interface{}) string { + switch val.(type) { + case *DocumentSet: + return "document set" + case *Document: + return "document" + case *Map: + return "map" + case *MapItem: + return "map item" + case *Array: + return "array" + case *ArrayItem: + return "array item" + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + return "integer" + case float32, float64: + return "float" + case bool: + return "boolean" + case nil: + return "null" + default: + return fmt.Sprintf("%T", val) + } +} + +func (ds *DocumentSet) GetPosition() *filepos.Position { return ds.Position } +func (d *Document) GetPosition() *filepos.Position { return d.Position } +func (m *Map) GetPosition() *filepos.Position { return m.Position } +func (mi *MapItem) GetPosition() *filepos.Position { return mi.Position } +func (a *Array) GetPosition() *filepos.Position { return a.Position } +func (ai *ArrayItem) GetPosition() *filepos.Position { return ai.Position } + +func (ds *DocumentSet) SetPosition(position *filepos.Position) { ds.Position = position } +func (d *Document) SetPosition(position *filepos.Position) { d.Position = position } +func (m *Map) SetPosition(position *filepos.Position) { m.Position = position } +func (mi *MapItem) SetPosition(position *filepos.Position) { mi.Position = position } +func (a *Array) SetPosition(position *filepos.Position) { a.Position = position } +func (ai *ArrayItem) SetPosition(position *filepos.Position) { ai.Position = position } + +func (ds *DocumentSet) SetValue(val interface{}) error { + return fmt.Errorf("cannot set value on a %s", TypeName(ds)) +} + +func (d *Document) SetValue(val interface{}) error { + d.ResetValue() + return d.AddValue(val) +} + +func (m *Map) SetValue(val interface{}) error { + return fmt.Errorf("cannot set value on a %s", TypeName(m)) +} + +func (mi *MapItem) SetValue(val interface{}) error { + mi.ResetValue() + return mi.AddValue(val) +} + +func (a *Array) SetValue(val interface{}) error { + return fmt.Errorf("cannot set value on an %s", TypeName(a)) +} + +func (ai *ArrayItem) SetValue(val interface{}) error { + ai.ResetValue() + return ai.AddValue(val) +} + +func isValidValue(val interface{}) bool { + switch val.(type) { + case *Map, *orderedmap.Map, + *Array, []interface{}, + int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, + float32, float64, + bool, + string, + nil: + return true + default: + return false + } +} + +func (ds *DocumentSet) ResetValue() { ds.Items = nil } +func (d *Document) ResetValue() { d.Value = nil } +func (m *Map) ResetValue() { m.Items = nil } +func (mi *MapItem) ResetValue() { mi.Value = nil } +func (a *Array) ResetValue() { a.Items = nil } +func (ai *ArrayItem) ResetValue() { ai.Value = nil } + +func (ds *DocumentSet) AddValue(val interface{}) error { + if item, ok := val.(*Document); ok { + ds.Items = append(ds.Items, item) + return nil + } + return fmt.Errorf("document sets can only contain documents; this is a %s", TypeName(val)) +} + +func (d *Document) AddValue(val interface{}) error { + if !isValidValue(val) { + return fmt.Errorf("documents can only contain arrays, maps, or scalars; this is a %s", TypeName(val)) + } + d.Value = val + return nil +} + +func (m *Map) AddValue(val interface{}) error { + if item, ok := val.(*MapItem); ok { + m.Items = append(m.Items, item) + return nil + } + return fmt.Errorf("maps can only contain map items; this is a %s", TypeName(val)) +} + +func (mi *MapItem) AddValue(val interface{}) error { + if !isValidValue(val) { + return fmt.Errorf("map items can only contain arrays, maps, or scalars; this is a %s", TypeName(val)) + } + mi.Value = val + return nil +} + +func (a *Array) AddValue(val interface{}) error { + if item, ok := val.(*ArrayItem); ok { + a.Items = append(a.Items, item) + return nil + } + return fmt.Errorf("arrays can only contain array items; this is a %s", TypeName(val)) +} + +func (ai *ArrayItem) AddValue(val interface{}) error { + if !isValidValue(val) { + return fmt.Errorf("array items can only contain maps, arrays, or scalars; this is a %s", TypeName(val)) + } + ai.Value = val + return nil +} + +func (ds *DocumentSet) GetValues() []interface{} { + var result []interface{} + for _, item := range ds.Items { + result = append(result, item) + } + return result +} + +func (d *Document) GetValues() []interface{} { return []interface{}{d.Value} } + +func (m *Map) GetValues() []interface{} { + var result []interface{} + for _, item := range m.Items { + result = append(result, item) + } + return result +} + +func (mi *MapItem) GetValues() []interface{} { return []interface{}{mi.Value} } + +func (a *Array) GetValues() []interface{} { + var result []interface{} + for _, item := range a.Items { + result = append(result, item) + } + return result +} + +func (ai *ArrayItem) GetValues() []interface{} { return []interface{}{ai.Value} } + +func (ds *DocumentSet) GetComments() []*Comment { return ds.Comments } +func (d *Document) GetComments() []*Comment { return d.Comments } +func (m *Map) GetComments() []*Comment { return m.Comments } +func (mi *MapItem) GetComments() []*Comment { return mi.Comments } +func (a *Array) GetComments() []*Comment { return a.Comments } +func (ai *ArrayItem) GetComments() []*Comment { return ai.Comments } + +// SetComments replaces comments with "c" +func (ds *DocumentSet) SetComments(c []*Comment) { ds.Comments = c } + +// SetComments replaces comments with "c" +func (d *Document) SetComments(c []*Comment) { d.Comments = c } + +// SetComments replaces comments with "c" +func (m *Map) SetComments(c []*Comment) { m.Comments = c } + +// SetComments replaces comments with "c" +func (mi *MapItem) SetComments(c []*Comment) { mi.Comments = c } + +// SetComments replaces comments with "c" +func (a *Array) SetComments(c []*Comment) { a.Comments = c } + +// SetComments replaces comments with "c" +func (ai *ArrayItem) SetComments(c []*Comment) { ai.Comments = c } + +func (ds *DocumentSet) addComments(comment *Comment) { ds.Comments = append(ds.Comments, comment) } +func (d *Document) addComments(comment *Comment) { d.Comments = append(d.Comments, comment) } +func (m *Map) addComments(comment *Comment) { + panic(fmt.Sprintf("Attempted to attach (%#v) to (%#v)", comment, m)) +} +func (mi *MapItem) addComments(comment *Comment) { mi.Comments = append(mi.Comments, comment) } +func (a *Array) addComments(comment *Comment) { + panic(fmt.Sprintf("Attempted to attach (%#v) to (%#v)", comment, a)) +} +func (ai *ArrayItem) addComments(comment *Comment) { ai.Comments = append(ai.Comments, comment) } + +func (ds *DocumentSet) GetAnnotations() interface{} { return ds.annotations } +func (d *Document) GetAnnotations() interface{} { return d.annotations } +func (m *Map) GetAnnotations() interface{} { return m.annotations } +func (mi *MapItem) GetAnnotations() interface{} { return mi.annotations } +func (a *Array) GetAnnotations() interface{} { return a.annotations } +func (ai *ArrayItem) GetAnnotations() interface{} { return ai.annotations } + +func (ds *DocumentSet) SetAnnotations(anns interface{}) { ds.annotations = anns } +func (d *Document) SetAnnotations(anns interface{}) { d.annotations = anns } +func (m *Map) SetAnnotations(anns interface{}) { m.annotations = anns } +func (mi *MapItem) SetAnnotations(anns interface{}) { mi.annotations = anns } +func (a *Array) SetAnnotations(anns interface{}) { a.annotations = anns } +func (ai *ArrayItem) SetAnnotations(anns interface{}) { ai.annotations = anns } + +// Below methods disallow marshaling of nodes directly +var _ []yaml.Marshaler = []yaml.Marshaler{&DocumentSet{}, &Document{}, &Map{}, &MapItem{}, &Array{}, &ArrayItem{}} + +// MarshalYAML panics because Nodes cannot be marshalled directly. +func (ds *DocumentSet) MarshalYAML() (interface{}, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", ds)) +} + +// MarshalYAML panics because Nodes cannot be marshalled directly. +func (d *Document) MarshalYAML() (interface{}, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", d)) +} + +// MarshalYAML panics because Nodes cannot be marshalled directly. +func (m *Map) MarshalYAML() (interface{}, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", m)) +} + +// MarshalYAML panics because Nodes cannot be marshalled directly. +func (mi *MapItem) MarshalYAML() (interface{}, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", mi)) +} + +// MarshalYAML panics because Nodes cannot be marshalled directly. +func (a *Array) MarshalYAML() (interface{}, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", a)) +} + +// MarshalYAML panics because Nodes cannot be marshalled directly. +func (ai *ArrayItem) MarshalYAML() (interface{}, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", ai)) +} + +// Below methods disallow marshaling of nodes directly +var _ []json.Marshaler = []json.Marshaler{&DocumentSet{}, &Document{}, &Map{}, &MapItem{}, &Array{}, &ArrayItem{}} + +// MarshalJSON panics because Nodes cannot be marshalled directly. +func (ds *DocumentSet) MarshalJSON() ([]byte, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", ds)) +} + +// MarshalJSON panics because Nodes cannot be marshalled directly. +func (d *Document) MarshalJSON() ([]byte, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", d)) +} + +// MarshalJSON panics because Nodes cannot be marshalled directly. +func (m *Map) MarshalJSON() ([]byte, error) { panic(fmt.Sprintf("Unexpected marshaling of %T", m)) } + +// MarshalJSON panics because Nodes cannot be marshalled directly. +func (mi *MapItem) MarshalJSON() ([]byte, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", mi)) +} + +// MarshalJSON panics because Nodes cannot be marshalled directly. +func (a *Array) MarshalJSON() ([]byte, error) { panic(fmt.Sprintf("Unexpected marshaling of %T", a)) } + +// MarshalJSON panics because Nodes cannot be marshalled directly. +func (ai *ArrayItem) MarshalJSON() ([]byte, error) { + panic(fmt.Sprintf("Unexpected marshaling of %T", ai)) +} + +func (ds *DocumentSet) sealed() {} +func (d *Document) sealed() {} +func (m *Map) sealed() {} +func (mi *MapItem) sealed() {} +func (a *Array) sealed() {} +func (ai *ArrayItem) sealed() {} + +// GetMeta returns the metadata named `name` that was previously attached via SetMeta() +func (ds *DocumentSet) GetMeta(name string) interface{} { + if ds.meta == nil { + ds.meta = make(map[string]interface{}) + } + return ds.meta[name] +} + +// SetMeta attaches metadata identified by `name` than can later be retrieved via GetMeta() +func (ds *DocumentSet) SetMeta(name string, data interface{}) { + if ds.meta == nil { + ds.meta = make(map[string]interface{}) + } + ds.meta[name] = data +} + +// GetMeta returns the metadata named `name` that was previously attached via SetMeta() +func (d *Document) GetMeta(name string) interface{} { + if d.meta == nil { + d.meta = make(map[string]interface{}) + } + return d.meta[name] +} + +// SetMeta attaches metadata identified by `name` than can later be retrieved via GetMeta() +func (d *Document) SetMeta(name string, data interface{}) { + if d.meta == nil { + d.meta = make(map[string]interface{}) + } + d.meta[name] = data +} + +// GetMeta returns the metadata named `name` that was previously attached via SetMeta() +func (m *Map) GetMeta(name string) interface{} { + if m.meta == nil { + m.meta = make(map[string]interface{}) + } + return m.meta[name] +} + +// SetMeta attaches metadata identified by `name` than can later be retrieved via GetMeta() +func (m *Map) SetMeta(name string, data interface{}) { + if m.meta == nil { + m.meta = make(map[string]interface{}) + } + m.meta[name] = data +} + +// GetMeta returns the metadata named `name` that was previously attached via SetMeta() +func (mi *MapItem) GetMeta(name string) interface{} { + if mi.meta == nil { + mi.meta = make(map[string]interface{}) + } + return mi.meta[name] +} + +// SetMeta attaches metadata identified by `name` than can later be retrieved via GetMeta() +func (mi *MapItem) SetMeta(name string, data interface{}) { + if mi.meta == nil { + mi.meta = make(map[string]interface{}) + } + mi.meta[name] = data +} + +// GetMeta returns the metadata named `name` that was previously attached via SetMeta() +func (a *Array) GetMeta(name string) interface{} { + if a.meta == nil { + a.meta = make(map[string]interface{}) + } + return a.meta[name] +} + +// SetMeta attaches metadata identified by `name` than can later be retrieved via GetMeta() +func (a *Array) SetMeta(name string, data interface{}) { + if a.meta == nil { + a.meta = make(map[string]interface{}) + } + a.meta[name] = data +} + +// GetMeta returns the metadata named `name` that was previously attached via SetMeta() +func (ai *ArrayItem) GetMeta(name string) interface{} { + if ai.meta == nil { + ai.meta = make(map[string]interface{}) + } + return ai.meta[name] +} + +// SetMeta attaches metadata identified by `name` than can later be retrieved via GetMeta() +func (ai *ArrayItem) SetMeta(name string, data interface{}) { + if ai.meta == nil { + ai.meta = make(map[string]interface{}) + } + ai.meta[name] = data +} diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/parser.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/parser.go similarity index 88% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/parser.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/parser.go index 9bdaa7b14..0eb6a57ca 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/parser.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/parser.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -14,8 +14,8 @@ import ( "strconv" "strings" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" ) var ( @@ -65,8 +65,7 @@ func (p *Parser) ParseBytes(data []byte, associatedName string) (*DocumentSet, e // since we always present line numbers as 1 based // (note that first doc marker may be several lines down) if !startsWithDocMarker && !docSet.Items[0].Position.IsKnown() { - docSet.Items[0].Position = filepos.NewPosition(1) - docSet.Items[0].Position.SetFile(associatedName) + docSet.Items[0].Position = filepos.NewPositionInFile(1, associatedName) } setPositionOfCollections(docSet, nil) @@ -103,7 +102,7 @@ func (p *Parser) parseBytes(data []byte, lineCorrection int) (*DocumentSet, erro Position: p.newDocPosition(dec.DocumentStartLine(), lineCorrection, len(docSet.Items) == 0, lines), } - allComments, unassignedComments := p.assignComments(doc, dec.Comments(), lineCorrection) + allComments, unassignedComments := p.assignComments(doc, dec.Comments(), lineCorrection, lines) docSet.AllComments = append(docSet.AllComments, allComments...) lastUnassignedComments = unassignedComments @@ -124,11 +123,12 @@ func (p *Parser) parseBytes(data []byte, lineCorrection int) (*DocumentSet, erro } // setPositionOfCollections assigns the Position of Maps and Arrays to their parent -// these kinds of nodes are not visible and therefore technically don't have a position. -// However, it is useful when communicating certain error cases to be able to reference -// a collection by line number. -// The position of the parent matches well with what the user sees. E.g. the MapItem that -// holds an Array is a great place to point at when referring to the entire array. +// +// these kinds of nodes are not visible and therefore technically don't have a position. +// However, it is useful when communicating certain error cases to be able to reference +// a collection by line number. +// The position of the parent matches well with what the user sees. E.g. the MapItem that +// holds an Array is a great place to point at when referring to the entire array. func setPositionOfCollections(node Node, parent Node) { if !node.GetPosition().IsKnown() { if parent != nil { @@ -184,7 +184,7 @@ func (p *Parser) parse(val interface{}, lineCorrection int, lines []string) inte } } -func (p *Parser) assignComments(val interface{}, comments []yaml.Comment, lineCorrection int) ([]*Comment, []*Comment) { +func (p *Parser) assignComments(val interface{}, comments []yaml.Comment, lineCorrection int, lines []string) ([]*Comment, []*Comment) { if p.opts.WithoutComments { return nil, nil } @@ -199,7 +199,7 @@ func (p *Parser) assignComments(val interface{}, comments []yaml.Comment, lineCo for _, comment := range comments { comment := &Comment{ Data: comment.Data, - Position: p.newPosition(comment.Line, lineCorrection, comment.Data), + Position: p.newPosition(comment.Line, lineCorrection, lines[comment.Line]), } allComments = append(allComments, comment) @@ -276,14 +276,11 @@ func (p *Parser) newDocPosition(actualLineNum, correction int, firstDoc bool, li } func (p *Parser) newPosition(actualLineNum, correction int, line string) *filepos.Position { - pos := filepos.NewPosition(actualLineNum + correction) - pos.SetFile(p.associatedName) + pos := filepos.NewPositionInFile(actualLineNum+correction, p.associatedName) pos.SetLine(line) return pos } func (p *Parser) newUnknownPosition() *filepos.Position { - pos := filepos.NewUnknownPosition() - pos.SetFile(p.associatedName) - return pos + return filepos.NewUnknownPositionInFile(p.associatedName) } diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/plain.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/plain.go similarity index 88% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/plain.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/plain.go index d4c8246ec..efd9d4711 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/plain.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/plain.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -7,7 +7,7 @@ import ( "fmt" "reflect" - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" + "carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2" ) func PlainMarshal(in interface{}) ([]byte, error) { diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/printer.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/printer.go similarity index 88% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/printer.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/printer.go index 607b957b4..b3b441f71 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/printer.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/printer.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -8,7 +8,7 @@ import ( "fmt" "io" - "github.com/k14s/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/filepos" ) type Printer struct { @@ -17,7 +17,8 @@ type Printer struct { } type PrinterOpts struct { - ExcludeRefs bool + ExcludeRefs bool + IncludeSrcLine bool } func NewPrinter(writer io.Writer) Printer { @@ -103,6 +104,10 @@ func (p Printer) ptrStr(node Node) string { func (p Printer) printComments(comments []*Comment, indent string, writer io.Writer) { for _, comment := range comments { - fmt.Fprintf(writer, "%scomment: %s: '%s'\n", indent, p.lineStr(comment.Position), comment.Data) + if p.opts.IncludeSrcLine { + fmt.Fprintf(writer, "%scomment: %s: '%s' -> '%s'\n", indent, p.lineStr(comment.Position), comment.Position.GetLine(), comment.Data) + } else { + fmt.Fprintf(writer, "%scomment: %s: '%s'\n", indent, p.lineStr(comment.Position), comment.Data) + } } } diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/printers.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/printers.go similarity index 87% rename from vendor/github.com/k14s/ytt/pkg/yamlmeta/printers.go rename to vendor/carvel.dev/ytt/pkg/yamlmeta/printers.go index cd83782b3..13c699d6f 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/printers.go +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/printers.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamlmeta @@ -8,7 +8,7 @@ import ( "fmt" "io" - "github.com/k14s/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/orderedmap" ) type DocumentPrinter interface { @@ -35,7 +35,7 @@ func (p *YAMLPrinter) Print(item *Document) error { bs, err := item.AsYAMLBytes() if err != nil { - return fmt.Errorf("marshaling doc: %s", err) + return fmt.Errorf("marshaling document: %s", err) } p.buf.Write(bs) return nil @@ -56,7 +56,7 @@ func (p JSONPrinter) Print(item *Document) error { bs, err := json.Marshal(orderedmap.Conversion{val}.AsUnorderedStringMaps()) if err != nil { - return fmt.Errorf("marshaling doc: %s", err) + return fmt.Errorf("marshaling document: %s", err) } p.buf.Write(bs) return nil diff --git a/vendor/carvel.dev/ytt/pkg/yamlmeta/walk.go b/vendor/carvel.dev/ytt/pkg/yamlmeta/walk.go new file mode 100644 index 000000000..b43ec1eca --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamlmeta/walk.go @@ -0,0 +1,76 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yamlmeta + +import "fmt" + +// Visitor performs an operation on the given Node while traversing the AST. +// Typically defines the action taken during a Walk(). +type Visitor interface { + Visit(Node) error +} + +// Walk traverses the tree starting at `n`, recursively, depth-first, invoking `v` on each node. +// if `v` returns non-nil error, the traversal is aborted. +func Walk(n Node, v Visitor) error { + err := v.Visit(n) + if err != nil { + return err + } + + for _, c := range n.GetValues() { + if cn, ok := c.(Node); ok { + err := Walk(cn, v) + if err != nil { + return err + } + } + } + return nil +} + +// VisitorWithParent performs an operation on the given Node while traversing the AST, including a reference to "node"'s +// +// parent node. +// +// Typically defines the action taken during a WalkWithParent(). +type VisitorWithParent interface { + VisitWithParent(value Node, parent Node, path string) error +} + +// WalkWithParent traverses the tree starting at `n`, recursively, depth-first, invoking `v` on each node and including +// +// a reference to "node"s parent node as well. +// +// if `v` returns non-nil error, the traversal is aborted. +func WalkWithParent(node Node, parent Node, path string, v VisitorWithParent) error { + err := v.VisitWithParent(node, parent, path) + if err != nil { + return err + } + + for idx, child := range node.GetValues() { + if childNode, ok := child.(Node); ok { + err = WalkWithParent(childNode, node, pathToNode(path, childNode, idx), v) + if err != nil { + return err + } + } + } + return nil +} + +func pathToNode(path string, node Node, idx int) string { + switch typedNode := node.(type) { + case *MapItem: + if path == "" { + return fmt.Sprintf("%s", typedNode.Key) + } + return fmt.Sprintf("%s.%s", path, typedNode.Key) + case *ArrayItem: + return fmt.Sprintf("%s[%d]", path, idx) + default: + return path + } +} diff --git a/vendor/carvel.dev/ytt/pkg/yamltemplate/doc.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/doc.go new file mode 100644 index 000000000..86ed5f1f0 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/doc.go @@ -0,0 +1,7 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package yamltemplate implements the YAML dialect of the ytt templating engine. +*/ +package yamltemplate diff --git a/vendor/github.com/k14s/ytt/pkg/yamltemplate/evaluation_ctx.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/evaluation_ctx.go similarity index 82% rename from vendor/github.com/k14s/ytt/pkg/yamltemplate/evaluation_ctx.go rename to vendor/carvel.dev/ytt/pkg/yamltemplate/evaluation_ctx.go index bac9446fe..205fc5803 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamltemplate/evaluation_ctx.go +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/evaluation_ctx.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamltemplate @@ -6,10 +6,10 @@ package yamltemplate import ( "fmt" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/orderedmap" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" ) const ( @@ -22,9 +22,8 @@ type EvaluationCtx struct { var _ template.EvaluationCtxDialect = EvaluationCtx{} -func (e EvaluationCtx) PrepareNode( - parentNode template.EvaluationNode, val template.EvaluationNode) error { - +// PrepareNode pre-processes the template.EvaluationNode so that the resulting AST fully reflects having been evaluated. +func (e EvaluationCtx) PrepareNode(parentNode template.EvaluationNode, val template.EvaluationNode) error { if typedMap, ok := parentNode.(*yamlmeta.Map); ok { if typedMapItem, ok := val.(*yamlmeta.MapItem); ok { return MapItemOverride{e.implicitMapKeyOverrides}.Apply(typedMap, typedMapItem, true) @@ -39,7 +38,7 @@ func (e EvaluationCtx) SetMapItemKey(node template.EvaluationNode, val interface return nil } - panic(fmt.Sprintf("expected node '%T' to be MapItem", node)) + panic(fmt.Sprintf("expected node '%T' to be '%T'", node, &yamlmeta.MapItem{})) } func (e EvaluationCtx) Replace( @@ -54,7 +53,7 @@ func (e EvaluationCtx) Replace( parentNode := parentNodes[len(parentNodes)-2] typedParentNode, ok := parentNode.(*yamlmeta.DocumentSet) if !ok { - return fmt.Errorf("expected to find document set, but was %T", parentNode) + return fmt.Errorf("expected to find document set, but was %s", yamlmeta.TypeName(parentNode)) } return e.replaceItemInDocSet(typedParentNode, typedCurrNode, val) @@ -67,7 +66,7 @@ func (e EvaluationCtx) Replace( parentNode := parentNodes[len(parentNodes)-2] typedParentNode, ok := parentNode.(*yamlmeta.Map) if !ok { - return fmt.Errorf("expected parent of map item to be map, but was %T", parentNode) + return fmt.Errorf("expected parent of map item to be a map, but was a %s", yamlmeta.TypeName(parentNode)) } return e.replaceItemInMap(typedParentNode, typedCurrNode, val) @@ -80,13 +79,13 @@ func (e EvaluationCtx) Replace( parentNode := parentNodes[len(parentNodes)-2] typedParentNode, ok := parentNode.(*yamlmeta.Array) if !ok { - return fmt.Errorf("expected parent of array item to be array, but was %T", parentNode) + return fmt.Errorf("expected parent of array item to be an array, but was a %s", yamlmeta.TypeName(parentNode)) } return e.replaceItemInArray(typedParentNode, typedCurrNode, val) default: - return fmt.Errorf("expected to replace document value, map item or array item, but found %T", typedCurrNode) + return fmt.Errorf("expected to replace document value, map item or array item, but found %s", yamlmeta.TypeName(typedCurrNode)) } } @@ -106,7 +105,7 @@ func (e EvaluationCtx) replaceItemInDocSet(dstDocSet *yamlmeta.DocumentSet, plac } } - return fmt.Errorf("expected to find placeholder doc in docset") + return fmt.Errorf("expected to find placeholder document in document set") } func (e EvaluationCtx) convertValToDocSetItems(val interface{}) ([]*yamlmeta.Document, error) { @@ -122,7 +121,7 @@ func (e EvaluationCtx) convertValToDocSetItems(val interface{}) ([]*yamlmeta.Doc result = typedVal.Items default: - return nil, fmt.Errorf("expected value to be docset, but was %T", val) + return nil, fmt.Errorf("expected value to be document set, but was %s", yamlmeta.TypeName(val)) } return result, nil @@ -172,7 +171,7 @@ func (e EvaluationCtx) convertValToMapItems(val interface{}, position *filepos.P return typedVal.Items, true, nil default: - return nil, false, fmt.Errorf("expected value to be map, but was %T", val) + return nil, false, fmt.Errorf("expected value to be map, but was %s", yamlmeta.TypeName(val)) } } @@ -208,7 +207,7 @@ func (e EvaluationCtx) convertValToArrayItems(val interface{}, position *filepos result = typedVal.Items default: - return nil, fmt.Errorf("expected value to be array, but was %T", val) + return nil, fmt.Errorf("expected value to be array, but was %s", yamlmeta.TypeName(val)) } return result, nil diff --git a/vendor/github.com/k14s/ytt/pkg/yamltemplate/go_value_with_yaml.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/go_value_with_yaml.go similarity index 73% rename from vendor/github.com/k14s/ytt/pkg/yamltemplate/go_value_with_yaml.go rename to vendor/carvel.dev/ytt/pkg/yamltemplate/go_value_with_yaml.go index a8381a1c3..7ac0d7156 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamltemplate/go_value_with_yaml.go +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/go_value_with_yaml.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamltemplate @@ -6,9 +6,9 @@ package yamltemplate import ( "fmt" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" "github.com/k14s/starlark-go/starlark" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" ) func NewGoValueWithYAML(val interface{}) tplcore.GoValue { @@ -17,7 +17,7 @@ func NewGoValueWithYAML(val interface{}) tplcore.GoValue { case *yamlmeta.Map, *yamlmeta.Array, *yamlmeta.DocumentSet: return &StarlarkFragment{valToConvert}, true case *yamlmeta.MapItem, *yamlmeta.ArrayItem, *yamlmeta.Document: - panic(fmt.Sprintf("NewComplexGoValue: Unexpected %T in conversion of fragment", valToConvert)) + panic(fmt.Sprintf("Unexpected %#v in conversion of fragment", valToConvert)) default: return starlark.None, false } diff --git a/vendor/github.com/k14s/ytt/pkg/yamltemplate/map_key_overrides.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/map_key_overrides.go similarity index 89% rename from vendor/github.com/k14s/ytt/pkg/yamltemplate/map_key_overrides.go rename to vendor/carvel.dev/ytt/pkg/yamltemplate/map_key_overrides.go index 4234ac313..dd4a83c21 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamltemplate/map_key_overrides.go +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/map_key_overrides.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamltemplate @@ -6,8 +6,8 @@ package yamltemplate import ( "fmt" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" ) const ( diff --git a/vendor/carvel.dev/ytt/pkg/yamltemplate/metas.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/metas.go new file mode 100644 index 000000000..0bd8c6fe1 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/metas.go @@ -0,0 +1,142 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yamltemplate + +import ( + "fmt" + "strings" + "unicode" + + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" +) + +var ( + nodeSpecificKeywords = map[string]string{ + "if/end": "if", + "else/end": "else", + "elif/end": "elif", + "for/end": "for", + "def/end": "def", + } +) + +// Metas are the collection of ytt YAML templating values parsed from the comments attached to a yamlmeta.Node +type Metas struct { + Block []*yamlmeta.Comment // meant to execute some code + Values []*yamlmeta.Comment // meant to return interpolated value + Annotations []CommentAndAnnotation + needsEnds int +} + +type CommentAndAnnotation struct { + Comment *yamlmeta.Comment + Annotation *template.Annotation +} + +// NewTemplateAnnotationFromYAMLComment parses "comment" into template.Annotation. +// nodePos is the position of the node to which "comment" is attached. +// +// When a comment contains a shorthand annotation (i.e. `#@ `): +// - if the comment is above its node, it's a template.AnnotationCode annotation: it's _merely_ contributing raw +// Starlark code. +// - if the comment is on the same line as its node, it's a template.AnnotationValue annotation: it's meant to set the +// value of the annotated node. +func NewTemplateAnnotationFromYAMLComment(comment *yamlmeta.Comment, nodePos *filepos.Position, opts template.MetaOpts) (template.Annotation, error) { + ann, err := template.NewAnnotationFromComment(comment.Data, comment.Position, opts) + if err != nil { + return template.Annotation{}, fmt.Errorf( + "Failed to parse line %s: '#%s': %s", comment.Position.AsIntString(), comment.Data, err) + } + + if len(ann.Name) == 0 { + // Default code and value annotations to make templates less verbose + ann.Name = template.AnnotationCode + + if nodePos.IsKnown() { + if comment.Position.LineNum() == nodePos.LineNum() { + ann.Name = template.AnnotationValue + } + } + } + + return ann, nil +} + +// extractMetas parses "metas" (i.e. code, values, and/or annotations) from node comments. +// Annotations that are consumable, such as AnnotationValue, AnnotationCode, and AnnotationComment, +// are processed and added for later consumption. Other annotations remain attached to the node. +// +// Returns the extracted metas and a copy of "node" with code and value type comments removed. +func extractMetas(node yamlmeta.Node, opts template.MetaOpts) (Metas, yamlmeta.Node, error) { + metas := Metas{} + + nonTemplateComments := []*yamlmeta.Comment{} + for _, comment := range node.GetComments() { + ann, err := NewTemplateAnnotationFromYAMLComment(comment, node.GetPosition(), opts) + if err != nil { + return metas, nil, err + } + + switch ann.Name { + case template.AnnotationValue: + if len(node.GetValues()) > 0 && node.GetValues()[0] != nil { + return metas, nil, fmt.Errorf( + "Expected YAML node at %s to have either computed or YAML value, but found both", + comment.Position.AsString()) + } + + metas.Values = append(metas.Values, &yamlmeta.Comment{ + Position: comment.Position, + Data: ann.Content, + }) + + case template.AnnotationCode: + if metas.needsEnds > 0 { + return metas, nil, fmt.Errorf( + "Unexpected code at %s after use of '*/end', expected YAML node", + comment.Position.AsString()) + } + + code := ann.Content + spacePrefix := metas.spacePrefix(code) + + for keyword, replacementKeyword := range nodeSpecificKeywords { + if strings.HasPrefix(code, spacePrefix+keyword) { + metas.needsEnds++ + code = strings.Replace(code, spacePrefix+keyword, spacePrefix+replacementKeyword, 1) + } + } + + metas.Block = append(metas.Block, &yamlmeta.Comment{ + Position: comment.Position, + Data: code, + }) + + case template.AnnotationComment: + // ytt comments are not considered "meta": no nothing. + // They _are_ considered part of the template's code, so these yamlmeta.Comments are "digested." + + default: + metas.Annotations = append(metas.Annotations, CommentAndAnnotation{comment, &ann}) + nonTemplateComments = append(nonTemplateComments, comment) + } + } + digestedNode := node.DeepCopyAsNode() + digestedNode.SetComments(nonTemplateComments) + + return metas, digestedNode, nil +} + +func (m Metas) NeedsEnd() bool { return m.needsEnds != 0 } + +func (m Metas) spacePrefix(str string) string { + for i, r := range str { + if !unicode.IsSpace(r) { + return str[:i] + } + } + return "" +} diff --git a/vendor/github.com/k14s/ytt/pkg/yamltemplate/starlark_fragment.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/starlark_fragment.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/yamltemplate/starlark_fragment.go rename to vendor/carvel.dev/ytt/pkg/yamltemplate/starlark_fragment.go index 0b1087298..006427fe9 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamltemplate/starlark_fragment.go +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/starlark_fragment.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamltemplate @@ -7,16 +7,17 @@ import ( "fmt" "reflect" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/syntax" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" ) const ( starlarkFragmentType = "yamlfragment" ) +// StarlarkFragment is an adapter for yamlmeta.Node values in Starlark code type StarlarkFragment struct { data interface{} } diff --git a/vendor/github.com/k14s/ytt/pkg/yamltemplate/template.go b/vendor/carvel.dev/ytt/pkg/yamltemplate/template.go similarity index 77% rename from vendor/github.com/k14s/ytt/pkg/yamltemplate/template.go rename to vendor/carvel.dev/ytt/pkg/yamltemplate/template.go index 17cea66d6..90a06c5ad 100644 --- a/vendor/github.com/k14s/ytt/pkg/yamltemplate/template.go +++ b/vendor/carvel.dev/ytt/pkg/yamltemplate/template.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yamltemplate @@ -7,10 +7,10 @@ import ( "bytes" "fmt" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/texttemplate" - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/texttemplate" + "carvel.dev/ytt/pkg/yamlmeta" ) const ( @@ -43,16 +43,14 @@ func hasTemplating(val interface{}) bool { return false } - metaOpts := MetasOpts{IgnoreUnknown: true} + metaOpts := template.MetaOpts{IgnoreUnknown: true} for _, comment := range node.GetComments() { - meta, err := NewTemplateMetaFromYAMLComment(comment, metaOpts) + ann, err := NewTemplateAnnotationFromYAMLComment(comment, node.GetPosition(), metaOpts) if err != nil { return false } - for _, meta := range meta.Annotations { - if meta.Name != template.AnnotationNameComment { - return true - } + if ann.Name != template.AnnotationComment { + return true } } @@ -68,6 +66,7 @@ func NewTemplate(name string, opts TemplateOpts) *Template { return &Template{name: name, opts: opts, instructions: template.NewInstructionSet()} } +// Compile converts a DocumentSet into code and metadata, returned via CompiledTemplate. func (e *Template) Compile(docSet *yamlmeta.DocumentSet) (*template.CompiledTemplate, error) { e.docSet = docSet e.nodes = template.NewNodes() @@ -98,11 +97,12 @@ type buildOpts struct { TextTemplatedStrings bool } -func (e *Template) build(val interface{}, parentNode yamlmeta.Node, parentTag template.NodeTag, opts buildOpts) ([]template.Line, error) { - node, ok := val.(yamlmeta.Node) +// build translates a document into a starlark program. This code is later evaluated to rebuild the output line by line, where annotated expressions are evaluated. +func (e *Template) build(nodeOrScalar interface{}, parentNode yamlmeta.Node, parentTag template.NodeTag, opts buildOpts) ([]template.Line, error) { + node, ok := nodeOrScalar.(yamlmeta.Node) if !ok { - if valStr, ok := val.(string); ok && opts.TextTemplatedStrings { - return e.buildString(valStr, parentNode, parentTag, e.instructions.NewSetNodeValue) + if s, ok := nodeOrScalar.(string); ok && opts.TextTemplatedStrings { + return e.buildString(s, parentNode, parentTag, e.instructions.NewSetNodeValue) } return []template.Line{{ @@ -111,18 +111,19 @@ func (e *Template) build(val interface{}, parentNode yamlmeta.Node, parentTag te }}, nil } - code := []template.Line{} - nodeTag := e.nodes.AddNode(node, parentTag) - - metas, err := NewMetas(node, MetasOpts{IgnoreUnknown: e.opts.IgnoreUnknownComments}) + metas, nodeForEval, err := extractMetas(node, template.MetaOpts{IgnoreUnknown: e.opts.IgnoreUnknownComments}) if err != nil { return nil, err } + nodeTag := e.nodes.AddNode(nodeForEval, parentTag) + if e.allowsTextTemplatedStrings(metas) { opts.TextTemplatedStrings = true } + code := []template.Line{} + for _, blk := range metas.Block { code = append(code, template.Line{ Instruction: e.instructions.NewCode(blk.Data), @@ -130,16 +131,17 @@ func (e *Template) build(val interface{}, parentNode yamlmeta.Node, parentTag te }) } - for _, metaAndAnn := range metas.Annotations { + for _, ann := range metas.Annotations { + e.nodes.AddAnnotation(nodeTag, *ann.Annotation) code = append(code, template.Line{ - Instruction: e.instructions.NewStartNodeAnnotation(nodeTag, *metaAndAnn.Annotation).WithDebug(e.debugComment(node)), - SourceLine: e.newSourceLine(metaAndAnn.Comment.Position), + Instruction: e.instructions.NewStartNodeAnnotation(nodeTag, *ann.Annotation).WithDebug(e.debugComment(nodeForEval)), + SourceLine: e.newSourceLine(ann.Comment.Position), }) } - if typedNode, ok := val.(*yamlmeta.MapItem); ok { - if keyStr, ok := typedNode.Key.(string); ok && opts.TextTemplatedStrings { - templateLines, err := e.buildString(keyStr, node, nodeTag, e.instructions.NewSetMapItemKey) + if mapItem, ok := nodeForEval.(*yamlmeta.MapItem); ok { + if keyStr, ok := mapItem.Key.(string); ok && opts.TextTemplatedStrings { + templateLines, err := e.buildString(keyStr, nodeForEval, nodeTag, e.instructions.NewSetMapItemKey) if err != nil { return nil, err } @@ -148,20 +150,20 @@ func (e *Template) build(val interface{}, parentNode yamlmeta.Node, parentTag te } code = append(code, template.Line{ - Instruction: e.instructions.NewStartNode(nodeTag).WithDebug(e.debugComment(node)), - SourceLine: e.newSourceLine(node.GetPosition()), + Instruction: e.instructions.NewStartNode(nodeTag).WithDebug(e.debugComment(nodeForEval)), + SourceLine: e.newSourceLine(nodeForEval.GetPosition()), }) if len(metas.Values) > 0 { for _, val := range metas.Values { code = append(code, template.Line{ - Instruction: e.instructions.NewSetNodeValue(nodeTag, val.Data).WithDebug(e.debugComment(node)), + Instruction: e.instructions.NewSetNodeValue(nodeTag, val.Data).WithDebug(e.debugComment(nodeForEval)), SourceLine: e.newSourceLine(val.Position), }) } } else { - for _, childVal := range node.GetValues() { - childCode, err := e.build(childVal, node, nodeTag, opts) + for _, childVal := range nodeForEval.GetValues() { + childCode, err := e.build(childVal, nodeForEval, nodeTag, opts) if err != nil { return nil, err } diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/all.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/all.go new file mode 100644 index 000000000..905b65c21 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/all.go @@ -0,0 +1,94 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yttlibrary + +import ( + "fmt" + + "carvel.dev/ytt/pkg/cmd/ui" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yttlibrary/overlay" + "github.com/k14s/starlark-go/starlark" + "github.com/k14s/starlark-go/starlarkstruct" +) + +var registeredExts []*starlarkstruct.Module + +// RegisterExt adds "mod" to the standard set of ytt library modules as an extension. +// An "extension" is a Starlark module that has external Go dependencies +// (as opposed to other Starlark modules in the ytt library that either +// have no dependencies or depend on the Go standard lib). +// This enables those using ytt as a Go module to opt-in (rather than be forced) +// to accept such dependencies. Only Carvel-maintained extensions can be registered; +// this reserves the `@ytt:` namespace. Integrators who want to write their own extensions +// should construct their own library. +func RegisterExt(mod *starlarkstruct.Module) { + switch mod.Name { + case "toml": + registeredExts = append(registeredExts, mod) + default: + panic("ytt library namespace can only be extended with ytt modules") + } +} + +type API struct { + modules map[string]starlark.StringDict +} + +// NewAPI builds an API instance to be used in executing a template. +func NewAPI( + replaceNodeFunc tplcore.StarlarkFunc, + dataMod DataModule, + libraryMod starlark.StringDict, + ui ui.UI) API { + + std := map[string]starlark.StringDict{ + "assert": NewAssertModule().AsModule(), + "math": NewMathModule(ui).AsModule(), + "regexp": RegexpAPI, + + // Hashes + "md5": MD5API, + "sha256": SHA256API, + + // Serializations + "base64": Base64API, + "json": JSONAPI, + "yaml": YAMLAPI, + "url": URLAPI, + "ip": IPAPI, + + // Templating + "template": NewTemplateModule(replaceNodeFunc).AsModule(), + "data": dataMod.AsModule(), + + // Object building + "struct": StructAPI, + "module": ModuleAPI, + "overlay": overlay.API, + + // Versioning + "version": VersionAPI, + + "library": libraryMod, + } + + for _, ext := range registeredExts { + // Double check that we are not overriding predefined library + if _, found := std[ext.Name]; found { + panic("Internal inconsistency: shadowing ytt library with an extension module") + } + std[ext.Name] = starlark.StringDict{ext.Name: ext} + } + + return API{std} +} + +func (a API) FindModule(module string) (starlark.StringDict, error) { + if module, found := a.modules[module]; found { + return module, nil + } + return nil, fmt.Errorf("builtin ytt library does not have module '%s' "+ + "(hint: is it available in newer version of ytt?)", module) +} diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/assert.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/assert.go new file mode 100644 index 000000000..78b1b07e2 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/assert.go @@ -0,0 +1,426 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yttlibrary + +import ( + "fmt" + + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template/core" + "github.com/k14s/starlark-go/starlark" + "github.com/k14s/starlark-go/starlarkstruct" + "github.com/k14s/starlark-go/syntax" +) + +// NewAssertModule constructs a new instance of AssertModule, respecting the "validations" experiment flag. +func NewAssertModule() AssertModule { + return AssertModule{} +} + +// AssertModule contains the definition of the @ytt:assert module. +type AssertModule struct{} + +// AsModule produces the corresponding Starlark module definition suitable for use in running a Starlark program. +func (m AssertModule) AsModule() starlark.StringDict { + members := starlark.StringDict{} + members["equals"] = starlark.NewBuiltin("assert.equals", core.ErrWrapper(m.Equals)) + members["fail"] = starlark.NewBuiltin("assert.fail", core.ErrWrapper(m.Fail)) + members["try_to"] = starlark.NewBuiltin("assert.try_to", core.ErrWrapper(m.TryTo)) + members["min"] = starlark.NewBuiltin("assert.min", core.ErrWrapper(m.Min)) + members["min_len"] = starlark.NewBuiltin("assert.min_len", core.ErrWrapper(m.MinLen)) + members["max"] = starlark.NewBuiltin("assert.max", core.ErrWrapper(m.Max)) + members["max_len"] = starlark.NewBuiltin("assert.max_len", core.ErrWrapper(m.MaxLen)) + members["not_null"] = starlark.NewBuiltin("assert.not_null", core.ErrWrapper(m.NotNull)) + members["one_not_null"] = starlark.NewBuiltin("assert.one_not_null", core.ErrWrapper(m.OneNotNull)) + members["one_of"] = starlark.NewBuiltin("assert.one_of", core.ErrWrapper(m.OneOf)) + return starlark.StringDict{ + "assert": &starlarkstruct.Module{ + Name: "assert", + Members: members, + }, + } +} + +// Equals compares two values for equality +func (m AssertModule) Equals(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 2 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 2) + } + + expected := args.Index(0) + if _, notOk := expected.(starlark.Callable); notOk { + return starlark.None, fmt.Errorf("expected argument not to be a function, but was %T", expected) + } + + actual := args.Index(1) + if _, notOk := actual.(starlark.Callable); notOk { + return starlark.None, fmt.Errorf("expected argument not to be a function, but was %T", actual) + } + + expectedString, err := m.asString(expected) + if err != nil { + return starlark.None, err + } + + actualString, err := m.asString(actual) + if err != nil { + return starlark.None, err + } + + if expectedString != actualString { + return starlark.None, fmt.Errorf("Not equal:\n"+ + "(expected type: %s)\n%s\n\n(was type: %s)\n%s", expected.Type(), expectedString, actual.Type(), actualString) + } + + return starlark.None, nil +} + +func (m AssertModule) asString(value starlark.Value) (string, error) { + starlarkValue, err := core.NewStarlarkValue(value).AsGoValue() + if err != nil { + return "", err + } + yamlString, err := yamlModule{}.Encode(starlarkValue) + if err != nil { + return "", err + } + return yamlString, nil +} + +// Fail is a core.StarlarkFunc that forces a Starlark failure. +func (m AssertModule) Fail(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + val, err := core.NewStarlarkValue(args.Index(0)).AsString() + if err != nil { + return starlark.None, err + } + + return starlark.None, fmt.Errorf("fail: %s", val) +} + +// TryTo is a core.StarlarkFunc that attempts to invoke the passed in starlark.Callable, converting any error into +// an error message. +func (m AssertModule) TryTo(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + lambda := args.Index(0) + if _, ok := lambda.(starlark.Callable); !ok { + return starlark.None, fmt.Errorf("expected argument to be a function, but was %T", lambda) + } + + retVal, err := starlark.Call(thread, lambda, nil, nil) + if err != nil { + return starlark.Tuple{starlark.None, starlark.String(err.Error())}, nil + } + return starlark.Tuple{retVal, starlark.None}, nil +} + +// Assertion encapsulates a rule (a predicate) that can be accessed in a Starlark expression (via the "check" attribute) +// or in Go (via CheckFunc()). +type Assertion struct { + check starlark.Callable + *core.StarlarkStruct +} + +// Type reports the name of this type in the Starlark type system. +func (a *Assertion) Type() string { return "@ytt:assert.assertion" } + +// CheckFunc returns the function that — given a value — makes this assertion on it. +func (a *Assertion) CheckFunc() starlark.Callable { + return a.check +} + +// ConversionHint helps the user get unstuck if they accidentally left an Assertion as a value in a YAML being +// encoded. +func (a *Assertion) ConversionHint() string { + return a.Type() + " does not encode (did you mean to call check()?)" +} + +// NewAssertionFromSource creates an Assertion whose "check" attribute is the lambda expression defined in "checkSrc". +func NewAssertionFromSource(funcName, checkSrc string, env starlark.StringDict) *Assertion { + expr, err := syntax.ParseExpr(funcName, checkSrc, syntax.BlockScanner) + if err != nil { + panic(fmt.Sprintf("Failed to parse internal expression (%s) :%s", checkSrc, err)) + } + thread := &starlark.Thread{Name: "ytt-internal"} + + evalExpr, err := starlark.EvalExpr(thread, expr, env) + if err != nil { + panic(fmt.Sprintf("Failed to evaluate internal expression (%s) given env=%s", checkSrc, env)) + } + + a := &Assertion{check: evalExpr.(*starlark.Function)} + m := orderedmap.NewMap() + m.Set("check", a.check) + a.StarlarkStruct = core.NewStarlarkStruct(m) + return a +} + +// NewAssertionFromStarlarkFunc creates an Assertion whose "check" attribute is "checkFunc". +func NewAssertionFromStarlarkFunc(funcName string, checkFunc core.StarlarkFunc) *Assertion { + a := &Assertion{check: starlark.NewBuiltin(funcName, checkFunc)} + + m := orderedmap.NewMap() + m.Set("check", a.check) + a.StarlarkStruct = core.NewStarlarkStruct(m) + + return a +} + +// NewAssertMaxLen produces an Assertion that a given sequence is at most "maximum" in length. +// +// see also: https://github.com/google/starlark-go/blob/master/doc/spec.md#len +func NewAssertMaxLen(maximum starlark.Int) *Assertion { + return NewAssertionFromSource( + "assert.max_len", + `lambda sequence: True if len(sequence) <= maximum else fail ("length = {}".format(len(sequence)))`, + starlark.StringDict{"maximum": maximum}, + ) +} + +// MaxLen is a core.StarlarkFunc wrapping NewAssertMaxLen() +func (m AssertModule) MaxLen(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + max, err := starlark.NumberToInt(args[0]) + if err != nil { + return nil, fmt.Errorf("expected value to be an number, but was %s", args[0].Type()) + } + return NewAssertMaxLen(max), nil +} + +// NewAssertMinLen produces an Assertion that a given sequence is at least "minimum" in length. +// +// see also: https://github.com/google/starlark-go/blob/master/doc/spec.md#len +func NewAssertMinLen(minimum starlark.Int) *Assertion { + return NewAssertionFromSource( + "assert.min_len", + `lambda sequence: True if len(sequence) >= minimum else fail ("length = {}".format(len(sequence)))`, + starlark.StringDict{"minimum": minimum}, + ) +} + +// MinLen is a core.StarlarkFunc wrapping NewAssertMinLen() +func (m AssertModule) MinLen(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + min, err := starlark.NumberToInt(args[0]) + if err != nil { + return nil, fmt.Errorf("expected value to be an number, but was %s", args[0].Type()) + } + return NewAssertMinLen(min), nil +} + +// NewAssertMin produces an Assertion that a given value is at least "minimum". +// +// see also:https://github.com/google/starlark-go/blob/master/doc/spec.md#comparisons +func NewAssertMin(min starlark.Value) *Assertion { + return NewAssertionFromSource( + "assert.min", + `lambda val: yaml.decode(yaml.encode(val)) >= yaml.decode(yaml.encode(min)) or fail("value < {}".format(yaml.decode(yaml.encode(min))))`, + starlark.StringDict{"min": min, "yaml": YAMLAPI["yaml"]}, + ) +} + +// Min is a core.StarlarkFunc wrapping NewAssertMin() +func (m AssertModule) Min(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + minFunc := NewAssertMin(args[0]) + return minFunc, nil +} + +// NewAssertMax produces an Assertion that a given value is at most "maximum". +// +// see also:https://github.com/google/starlark-go/blob/master/doc/spec.md#comparisons +func NewAssertMax(max starlark.Value) *Assertion { + return NewAssertionFromSource( + "assert.max", + `lambda val: yaml.decode(yaml.encode(val)) <= yaml.decode(yaml.encode(max)) or fail("value > {}".format(yaml.decode(yaml.encode(max))))`, + starlark.StringDict{"max": max, "yaml": YAMLAPI["yaml"]}, + ) +} + +// Max is a core.StarlarkFunc wrapping NewAssertMax() +func (m AssertModule) Max(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + maxFunc := NewAssertMax(args[0]) + return maxFunc, nil +} + +// NewAssertNotNull produces an Assertion that a given value is not null. +func NewAssertNotNull() *Assertion { + return NewAssertionFromSource( + "assert.not_null", + `lambda value: value != None or fail("value is null")`, + starlark.StringDict{}, + ) +} + +// NotNull is a core.StarlarkFunc wrapping NewAssertNotNull() +func (m AssertModule) NotNull(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() > 1 { + return starlark.None, fmt.Errorf("got %d arguments, want at most %d", args.Len(), 1) + } + + result := NewAssertNotNull() + if args.Len() == 0 { + return result, nil + } + + // support shorthand syntax: assert.not_null(value) + return starlark.Call(thread, result.CheckFunc(), args, []starlark.Tuple{}) +} + +// NewAssertOneNotNull produces an Assertion that a given value is a map having exactly one item with a non-null value. +func NewAssertOneNotNull(keys starlark.Sequence) *Assertion { + return NewAssertionFromStarlarkFunc("assert.one_not_null", AssertModule{}.oneNotNullCheck(keys)) +} + +// OneNotNull is a core.StarlarkFunc wrapping NewAssertOneNotNull() +func (m AssertModule) OneNotNull(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() > 1 { + return starlark.None, fmt.Errorf("got %d arguments, want %d", args.Len(), 1) + } + + if args.Len() == 0 { + return NewAssertOneNotNull(nil), nil + } + if b, ok := args[0].(starlark.Bool); ok { + if b.Truth() { + return NewAssertOneNotNull(nil), nil + } + return nil, fmt.Errorf("one_not_null() cannot be False") + } + + seq, ok := args[0].(starlark.Sequence) + if !ok { + return nil, fmt.Errorf("expected a sequence of keys, but was a '%s'", args[0].Type()) + } + return NewAssertOneNotNull(seq), nil +} + +func (m AssertModule) oneNotNullCheck(keys starlark.Sequence) core.StarlarkFunc { + return func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("check: got %d arguments, want %d", args.Len(), 1) + } + val, err := m.yamlEncodeDecode(args[0]) + if err != nil { + return nil, err + } + dict, ok := val.(*starlark.Dict) + if !ok { + return nil, fmt.Errorf("check: value must be a map or dict, but was '%s'", val.Type()) + } + + var keysToCheck []starlark.Value + + if keys == nil { + keysToCheck = append(keysToCheck, dict.Keys()...) + } else { + var key starlark.Value + keys := keys.Iterate() + for keys.Next(&key) { + v, err := m.yamlEncodeDecode(key) + if err != nil { + return nil, err + } + keysToCheck = append(keysToCheck, v) + } + } + + var nulls, notNulls []starlark.Value + + for _, key := range keysToCheck { + value, found, err := dict.Get(key) + if err != nil { + return nil, fmt.Errorf("check: unexpected error while looking up key %s in dict %s", key, dict) + } + if !found { + // allow schema to catch this (see also https://github.com/carvel-dev/ytt/issues/722) + nulls = append(nulls, key) + } + if value == starlark.None { + nulls = append(nulls, key) + } else { + notNulls = append(notNulls, key) + } + } + + switch len(notNulls) { + case 0: + if len(dict.Keys()) == 0 { + return nil, fmt.Errorf("check: value is empty") + } + return nil, fmt.Errorf("check: all values are null") + case 1: + return starlark.True, nil + default: + return nil, fmt.Errorf("check: %s are not null", starlark.NewList(notNulls).String()) + } + } +} + +// NewAssertOneOf produces an Assertion that a given value is one of a pre-defined set. +// +// see also:https://github.com/google/starlark-go/blob/master/doc/spec.md#membership-tests +func NewAssertOneOf(enum starlark.Sequence) *Assertion { + return NewAssertionFromSource( + "assert.one_of", + `lambda val: yaml.decode(yaml.encode(val)) in yaml.decode(yaml.encode(enum)) or fail("not one of allowed values")`, + starlark.StringDict{"enum": enum, "yaml": YAMLAPI["yaml"]}, + ) +} + +// OneOf is a core.StarlarkFunc wrapping NewAssertOneOf() +func (m AssertModule) OneOf(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() == 0 { + return starlark.None, fmt.Errorf("got %d arguments, want at least %d", args.Len(), 1) + } + + enum := args[0] + if args.Len() > 1 { + enum = args + } + + seq, ok := enum.(starlark.Sequence) + if !ok { + return nil, fmt.Errorf("expected a sequence, but was a '%s'", enum.Type()) + } + + maxFunc := NewAssertOneOf(seq) + return maxFunc, nil +} + +func (m AssertModule) yamlEncodeDecode(val starlark.Value) (starlark.Value, error) { + yaml := yamlModule{} + value, err := core.NewStarlarkValue(val).AsGoValue() + if err != nil { + return nil, err + } + encode, err := yaml.Encode(value) + if err != nil { + return nil, err + } + val, err = yaml.Decode(encode) + if err != nil { + return nil, err + } + return val, nil +} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/base64.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/base64.go similarity index 90% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/base64.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/base64.go index 07c560818..d94573b91 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/base64.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/base64.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -7,9 +7,9 @@ import ( "encoding/base64" "fmt" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" ) var ( @@ -70,7 +70,7 @@ func (b base64Module) Decode(thread *starlark.Thread, f *starlark.Builtin, args func (b base64Module) buildEncoding(kwargs []starlark.Tuple) (*base64.Encoding, error) { var encoding *base64.Encoding = base64.StdEncoding - isURL, err := core.BoolArg(kwargs, "url") + isURL, err := core.BoolArg(kwargs, "url", false) if err != nil { return nil, err } @@ -78,7 +78,7 @@ func (b base64Module) buildEncoding(kwargs []starlark.Tuple) (*base64.Encoding, encoding = base64.URLEncoding } - isRaw, err := core.BoolArg(kwargs, "raw") + isRaw, err := core.BoolArg(kwargs, "raw", false) if err != nil { return nil, err } @@ -86,7 +86,7 @@ func (b base64Module) buildEncoding(kwargs []starlark.Tuple) (*base64.Encoding, encoding = encoding.WithPadding(base64.NoPadding) } - isStrict, err := core.BoolArg(kwargs, "strict") + isStrict, err := core.BoolArg(kwargs, "strict", false) if err != nil { return nil, err } diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/data.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/data.go similarity index 95% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/data.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/data.go index f7bf530d4..fd382afb8 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/data.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/data.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -6,10 +6,10 @@ package yttlibrary import ( "fmt" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" ) type DataModule struct { diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/doc.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/doc.go new file mode 100644 index 000000000..a32eb612b --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/doc.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package yttlibrary implements the "Standard Library" of modules that are +built-in to the ytt templating engine. +*/ +package yttlibrary diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/ip.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/ip.go new file mode 100644 index 000000000..5f5c3b8d3 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/ip.go @@ -0,0 +1,158 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yttlibrary + +import ( + "fmt" + "net" + + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template/core" + "github.com/k14s/starlark-go/starlark" + "github.com/k14s/starlark-go/starlarkstruct" +) + +var ( + // IPAPI describes the contents of "@ytt:ip" module of the ytt standard library. + IPAPI = starlark.StringDict{ + "ip": &starlarkstruct.Module{ + Name: "ip", + Members: starlark.StringDict{ + "parse_addr": starlark.NewBuiltin("ip.parse_addr", core.ErrWrapper(ipModule{}.ParseAddr)), + "parse_cidr": starlark.NewBuiltin("ip.parse_cidr", core.ErrWrapper(ipModule{}.ParseCIDR)), + }, + }, + } +) + +type ipModule struct{} + +func (m ipModule) ParseAddr(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("expected exactly one argument") + } + + ipStr, err := core.NewStarlarkValue(args.Index(0)).AsString() + if err != nil { + return starlark.None, err + } + + parsedIP := net.ParseIP(ipStr) + if parsedIP == nil { + return starlark.None, fmt.Errorf("invalid IP address: %s", ipStr) + } + return (&IPAddrValue{parsedIP, nil}).AsStarlarkValue(), nil +} + +// IPAddrValue stores a parsed IP +type IPAddrValue struct { + addr net.IP + *core.StarlarkStruct // TODO: keep authorship of the interface by delegating instead of embedding +} + +const ipAddrTypeName = "ip.addr" + +// Type reports the name of this type as seen from a Starlark program (i.e. via the `type()` built-in) +func (av *IPAddrValue) Type() string { return "@ytt:" + ipAddrTypeName } + +// AsStarlarkValue converts this instance into a value suitable for use in a Starlark program. +func (av *IPAddrValue) AsStarlarkValue() starlark.Value { + m := orderedmap.NewMap() + m.Set("is_ipv4", starlark.NewBuiltin(ipAddrTypeName+".is_ipv4", core.ErrWrapper(av.IsIPv4))) + m.Set("is_ipv6", starlark.NewBuiltin(ipAddrTypeName+".is_ipv6", core.ErrWrapper(av.IsIPv6))) + m.Set("string", starlark.NewBuiltin(ipAddrTypeName+".string", core.ErrWrapper(av.string))) + av.StarlarkStruct = core.NewStarlarkStruct(m) + return av +} + +// ConversionHint provides a hint on how the user can explicitly convert this value to a type that can be automatically encoded. +func (av *IPAddrValue) ConversionHint() string { + return av.Type() + " does not automatically encode (hint: use .string())" +} + +// IsIPv4 is a core.StarlarkFunc that reveals whether this value is an IPv4 address. +func (av *IPAddrValue) IsIPv4(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 0 { + return starlark.None, fmt.Errorf("expected no argument") + } + isV4 := av.addr != nil && av.addr.To4() != nil + return starlark.Bool(isV4), nil +} + +// IsIPv6 is a core.StarlarkFunc that reveals whether this value is an IPv6 address. +func (av *IPAddrValue) IsIPv6(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 0 { + return starlark.None, fmt.Errorf("expected no argument") + } + isV6 := av.addr != nil && av.addr.To4() == nil + return starlark.Bool(isV6), nil +} + +func (av *IPAddrValue) string(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 0 { + return starlark.None, fmt.Errorf("expected no argument") + } + return starlark.String(av.addr.String()), nil +} + +// ParseCIDR is a core.StarlarkFunc that extracts the IP address and IP network value from a CIDR expression +func (m ipModule) ParseCIDR(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("expected exactly one argument") + } + + cidrStr, err := core.NewStarlarkValue(args.Index(0)).AsString() + if err != nil { + return starlark.None, err + } + + parsedIP, parsedNet, err := net.ParseCIDR(cidrStr) + if err != nil { + return starlark.None, err + } + + return starlark.Tuple{(&IPAddrValue{parsedIP, nil}).AsStarlarkValue(), (&IPNetValue{parsedNet, nil}).AsStarlarkValue()}, nil +} + +// IPNetValue holds the data for an instance of an IP Network value +type IPNetValue struct { + net *net.IPNet + *core.StarlarkStruct // TODO: keep authorship of the interface by delegating instead of embedding +} + +const ipNetTypeName = "ip.net" + +// Type reports the name of this type as seen from a Starlark program (i.e. via the `type()` built-in) +func (inv *IPNetValue) Type() string { return "@ytt:" + ipNetTypeName } + +// AsStarlarkValue converts this instance into a value suitable for use in a Starlark program. +func (inv *IPNetValue) AsStarlarkValue() starlark.Value { + m := orderedmap.NewMap() + m.Set("addr", starlark.NewBuiltin(ipNetTypeName+".addr", core.ErrWrapper(inv.Addr))) + m.Set("string", starlark.NewBuiltin(ipNetTypeName+".string", core.ErrWrapper(inv.string))) + inv.StarlarkStruct = core.NewStarlarkStruct(m) + return inv +} + +// ConversionHint provides a hint on how the user can explicitly convert this value to a type that can be automatically encoded. +func (inv *IPNetValue) ConversionHint() string { + return inv.Type() + " does not automatically encode (hint: use .string())" +} + +// Addr is a core.StarlarkFunc that returns the masked address portion of the network value +func (inv *IPNetValue) Addr(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 0 { + return starlark.None, fmt.Errorf("expected no argument") + } + + ip := &IPAddrValue{inv.net.IP, nil} + return ip.AsStarlarkValue(), nil +} + +func (inv *IPNetValue) string(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 0 { + return starlark.None, fmt.Errorf("expected no argument") + } + return starlark.String(inv.net.String()), nil +} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/json.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/json.go similarity index 64% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/json.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/json.go index 9171d2588..f4e2269fc 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/json.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/json.go @@ -1,21 +1,23 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary import ( + "bytes" "encoding/json" "fmt" "strings" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/orderedmap" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" ) var ( + // JSONAPI contains the definition of the @ytt:json module JSONAPI = starlark.StringDict{ "json": &starlarkstruct.Module{ Name: "json", @@ -25,18 +27,20 @@ var ( }, }, } - JSONKWARGS = map[string]struct{}{ - "indent": struct{}{}, - } ) type jsonModule struct{} +// Encode is a core.StarlarkFunc that renders the provided input into a JSON formatted string func (b jsonModule) Encode(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { if args.Len() != 1 { return starlark.None, fmt.Errorf("expected exactly one argument") } - if err := core.CheckArgNames(kwargs, JSONKWARGS); err != nil { + allowedKWArgs := map[string]struct{}{ + "indent": {}, + "escape_html": {}, + } + if err := core.CheckArgNames(kwargs, allowedKWArgs); err != nil { return starlark.None, err } @@ -47,26 +51,36 @@ func (b jsonModule) Encode(thread *starlark.Thread, f *starlark.Builtin, args st val = orderedmap.Conversion{yamlmeta.NewGoFromAST(val)}.AsUnorderedStringMaps() var valBs []byte + buffer := bytes.NewBuffer(valBs) indent, err := core.Int64Arg(kwargs, "indent") if err != nil { return starlark.None, err } - if indent > 4 || indent < 0 { - return starlark.None, fmt.Errorf("indent value must be between 0 and 4") + if indent < 0 || indent > 8 { + // mitigate https://cwe.mitre.org/data/definitions/409.html + return starlark.None, fmt.Errorf("indent value must be between 0 and 8") + } + + escapeHTML, err := core.BoolArg(kwargs, "escape_html", true) + if err != nil { + return starlark.None, err } + + encoder := json.NewEncoder(buffer) if indent > 0 { - valBs, err = json.MarshalIndent(val, "", strings.Repeat(" ", int(indent))) - } else { - valBs, err = json.Marshal(val) + encoder.SetIndent("", strings.Repeat(" ", int(indent))) } + encoder.SetEscapeHTML(escapeHTML) - if err != nil { + if err := encoder.Encode(val); err != nil { return starlark.None, err } - return starlark.String(string(valBs)), nil + res := strings.TrimSuffix(buffer.String(), "\n") + return starlark.String(res), nil } +// Decode is a core.StarlarkFunc that parses the provided input from JSON format into dicts, lists, and scalars func (b jsonModule) Decode(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { if args.Len() != 1 { return starlark.None, fmt.Errorf("expected exactly one argument") diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/math.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/math.go new file mode 100644 index 000000000..8becea324 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/math.go @@ -0,0 +1,270 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +// Copyright 2021 The Bazel Authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package yttlibrary + +import ( + "fmt" + "math" + + "carvel.dev/ytt/pkg/cmd/ui" + "carvel.dev/ytt/pkg/template/core" + "github.com/k14s/starlark-go/starlark" + "github.com/k14s/starlark-go/starlarkstruct" +) + +// MathModule contains the definition of the @ytt:math module. +// It contains math-related functions and constants. +// The module defines the following functions: +// +// ceil(x) - Returns the ceiling of x, the smallest integer greater than or equal to x. +// copysign(x, y) - Returns a value with the magnitude of x and the sign of y. +// fabs(x) - Returns the absolute value of x as float. +// floor(x) - Returns the floor of x, the largest integer less than or equal to x. +// mod(x, y) - Returns the floating-point remainder of x/y. The magnitude of the result is less than y and its sign agrees with that of x. +// pow(x, y) - Returns x**y, the base-x exponential of y. +// remainder(x, y) - Returns the IEEE 754 floating-point remainder of x/y. +// round(x) - Returns the nearest integer, rounding half away from zero. +// +// exp(x) - Returns e raised to the power x, where e = 2.718281… is the base of natural logarithms. +// sqrt(x) - Returns the square root of x. +// +// acos(x) - Returns the arc cosine of x, in radians. +// asin(x) - Returns the arc sine of x, in radians. +// atan(x) - Returns the arc tangent of x, in radians. +// atan2(y, x) - Returns atan(y / x), in radians. +// The result is between -pi and pi. +// The vector in the plane from the origin to point (x, y) makes this angle with the positive X axis. +// The point of atan2() is that the signs of both inputs are known to it, so it can compute the correct +// quadrant for the angle. +// For example, atan(1) and atan2(1, 1) are both pi/4, but atan2(-1, -1) is -3*pi/4. +// cos(x) - Returns the cosine of x, in radians. +// hypot(x, y) - Returns the Euclidean norm, sqrt(x*x + y*y). This is the length of the vector from the origin to point (x, y). +// sin(x) - Returns the sine of x, in radians. +// tan(x) - Returns the tangent of x, in radians. +// +// degrees(x) - Converts angle x from radians to degrees. +// radians(x) - Converts angle x from degrees to radians. +// +// acosh(x) - Returns the inverse hyperbolic cosine of x. +// asinh(x) - Returns the inverse hyperbolic sine of x. +// atanh(x) - Returns the inverse hyperbolic tangent of x. +// cosh(x) - Returns the hyperbolic cosine of x. +// sinh(x) - Returns the hyperbolic sine of x. +// tanh(x) - Returns the hyperbolic tangent of x. +// +// log(x, base) - Returns the logarithm of x in the given base, or natural logarithm by default. +// +// gamma(x) - Returns the Gamma function of x. +// +// All functions accept both int and float values as arguments. +// +// The module also defines approximations of the following constants: +// +// e - The base of natural logarithms, approximately 2.71828. +// pi - The ratio of a circle's circumference to its diameter, approximately 3.14159. +type MathModule struct { + ui ui.UI +} + +// hasWarned indicates whether the caveat associated with using this module has been displayed. +// This flag ensures we display that warning only once; more than once and its noise. +var hasWarned bool + +// NewMathModule constructs a new instance of MathModule with the configured UI (to enable displaying a warning). +func NewMathModule(ui ui.UI) MathModule { + return MathModule{ui: ui} +} + +// AsModule produces the corresponding Starlark module definition suitable for use in running a Starlark program. +func (m MathModule) AsModule() starlark.StringDict { + return starlark.StringDict{ + "math": &starlarkstruct.Module{ + Name: "math", + Members: starlark.StringDict{ + "ceil": starlark.NewBuiltin("ceil", m.warnOnCall(core.ErrWrapper(m.ceil))), + "copysign": m.newBinaryBuiltin("copysign", math.Copysign), + "fabs": m.newUnaryBuiltin("fabs", math.Abs), + "floor": starlark.NewBuiltin("floor", m.warnOnCall(core.ErrWrapper(m.floor))), + "mod": m.newBinaryBuiltin("round", math.Mod), + "pow": m.newBinaryBuiltin("pow", math.Pow), + "remainder": m.newBinaryBuiltin("remainder", math.Remainder), + "round": m.newUnaryBuiltin("round", math.Round), + + "exp": m.newUnaryBuiltin("exp", math.Exp), + "sqrt": m.newUnaryBuiltin("sqrt", math.Sqrt), + + "acos": m.newUnaryBuiltin("acos", math.Acos), + "asin": m.newUnaryBuiltin("asin", math.Asin), + "atan": m.newUnaryBuiltin("atan", math.Atan), + "atan2": m.newBinaryBuiltin("atan2", math.Atan2), + "cos": m.newUnaryBuiltin("cos", math.Cos), + "hypot": m.newBinaryBuiltin("hypot", math.Hypot), + "sin": m.newUnaryBuiltin("sin", math.Sin), + "tan": m.newUnaryBuiltin("tan", math.Tan), + + "degrees": m.newUnaryBuiltin("degrees", m.degrees), + "radians": m.newUnaryBuiltin("radians", m.radians), + + "acosh": m.newUnaryBuiltin("acosh", math.Acosh), + "asinh": m.newUnaryBuiltin("asinh", math.Asinh), + "atanh": m.newUnaryBuiltin("atanh", math.Atanh), + "cosh": m.newUnaryBuiltin("cosh", math.Cosh), + "sinh": m.newUnaryBuiltin("sinh", math.Sinh), + "tanh": m.newUnaryBuiltin("tanh", math.Tanh), + + "log": starlark.NewBuiltin("log", m.warnOnCall(m.log)), + + "gamma": m.newUnaryBuiltin("gamma", math.Gamma), + + "e": starlark.Float(math.E), + "pi": starlark.Float(math.Pi), + }, + }, + } +} + +// newUnaryBuiltin wraps a unary floating-point Go function +// as a Starlark built-in that accepts int or float arguments. +func (m MathModule) newUnaryBuiltin(name string, fn func(float64) float64) *starlark.Builtin { + return starlark.NewBuiltin(name, m.warnOnCall(core.ErrWrapper(func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("expected exactly one argument") + } + + x, err := core.NewStarlarkValue(args.Index(0)).AsFloat64() + if err != nil { + return starlark.None, err + } + + return starlark.Float(fn(x)), nil + }))) +} + +// newBinaryBuiltin wraps a binary floating-point Go function +// as a Starlark built-in that accepts int or float arguments. +func (m MathModule) newBinaryBuiltin(name string, fn func(float64, float64) float64) *starlark.Builtin { + return starlark.NewBuiltin(name, m.warnOnCall(core.ErrWrapper(func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 2 { + return starlark.None, fmt.Errorf("expected exactly two arguments") + } + + x, err := core.NewStarlarkValue(args.Index(0)).AsFloat64() + if err != nil { + return starlark.None, err + } + + y, err := core.NewStarlarkValue(args.Index(1)).AsFloat64() + if err != nil { + return starlark.None, err + } + return starlark.Float(fn(x, y)), nil + }))) +} + +// warnOnCall ensures that if any wrapped function is called, the user is warned that the execution is no longer guaranteed to be deterministic. +func (m MathModule) warnOnCall(wrappedFunc core.StarlarkFunc) core.StarlarkFunc { + return func(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (val starlark.Value, resultErr error) { + if !hasWarned { + m.ui.Warnf("\nWarning: a function from the @ytt:math module is used in this invocation; this module does not guarantee bit-identical results across CPU architectures.\n") + hasWarned = true + } + return wrappedFunc(thread, f, args, kwargs) + } +} + +// log wraps the Log function +// +// as a Starlark built-in that accepts int or float arguments. +func (m MathModule) log(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + var ( + xValue starlark.Value + baseValue starlark.Value = starlark.Float(math.E) + ) + if err := starlark.UnpackPositionalArgs("log", args, kwargs, 1, &xValue, &baseValue); err != nil { + return nil, err + } + + x, err := core.NewStarlarkValue(xValue).AsFloat64() + if err != nil { + return starlark.None, err + } + + base, err := core.NewStarlarkValue(baseValue).AsFloat64() + if err != nil { + return starlark.None, err + } + + return starlark.Float(math.Log(x) / math.Log(base)), nil +} + +func (m MathModule) ceil(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + var x starlark.Value + + if err := starlark.UnpackPositionalArgs("ceil", args, kwargs, 1, &x); err != nil { + return nil, err + } + + switch t := x.(type) { + case starlark.Int: + return t, nil + case starlark.Float: + return starlark.NumberToInt(starlark.Float(math.Ceil(float64(t)))) + } + + return nil, fmt.Errorf("expected float value, but was %T", x) +} + +func (m MathModule) floor(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + var x starlark.Value + + if err := starlark.UnpackPositionalArgs("floor", args, kwargs, 1, &x); err != nil { + return nil, err + } + + switch t := x.(type) { + case starlark.Int: + return t, nil + case starlark.Float: + return starlark.NumberToInt(starlark.Float(math.Floor(float64(t)))) + } + + return nil, fmt.Errorf("expected float value, but was %T", x) +} + +func (m MathModule) degrees(x float64) float64 { + return 360 * x / (2 * math.Pi) +} + +func (m MathModule) radians(x float64) float64 { + return 2 * math.Pi * x / 360 +} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/md5.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/md5.go similarity index 91% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/md5.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/md5.go index cd931b15c..1e4dae784 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/md5.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/md5.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -7,9 +7,9 @@ import ( "crypto/md5" "fmt" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" ) var ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/module.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/module.go similarity index 84% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/module.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/module.go index 71ad9866a..55566569e 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/module.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/module.go @@ -1,12 +1,12 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary import ( + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" ) var ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/annotations.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/annotations.go similarity index 92% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/annotations.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/annotations.go index b31793adb..91c5d18a9 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/annotations.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/annotations.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,8 +6,8 @@ package overlay import ( "fmt" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" ) const ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/api.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/api.go similarity index 96% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/api.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/api.go index 147c8bb49..e9e04c67a 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/api.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/api.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -7,11 +7,11 @@ import ( "fmt" "reflect" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" ) var ( @@ -169,7 +169,7 @@ func (b overlayModule) compareByMapKey(keyName string, oldVal, newVal interface{ func (b overlayModule) pullOutMapValue(keyName string, val interface{}) (interface{}, error) { typedMap, ok := val.(*yamlmeta.Map) if !ok { - return starlark.None, fmt.Errorf("Expected value to be map, but was %T", val) + return starlark.None, fmt.Errorf("Expected value to be map, but was %s", yamlmeta.TypeName(val)) } for _, item := range typedMap.Items { @@ -178,7 +178,7 @@ func (b overlayModule) pullOutMapValue(keyName string, val interface{}) (interfa } } - return starlark.None, fmt.Errorf("Expected to find mapitem with key '%s', but did not", keyName) + return starlark.None, fmt.Errorf("Expected to find map item with key '%s', but did not", keyName) } func (b overlayModule) Subset( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/array.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/array.go similarity index 92% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/array.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/array.go index b6ee71c9f..a6b074b3d 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/array.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/array.go @@ -1,10 +1,10 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay import ( - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamlmeta" ) func (o Op) mergeArrayItem( @@ -159,7 +159,7 @@ func (o Op) insertArrayItem( return err } - insertAnn, err := NewInsertAnnotation(newItem) + insertAnn, err := NewInsertAnnotation(newItem, o.Thread) if err != nil { return err } @@ -171,12 +171,23 @@ func (o Op) insertArrayItem( for _, leftIdx := range leftIdxs { if i == leftIdx { matched = true + + newVal, err := insertAnn.Value(leftItem) + if err != nil { + return err + } + insertItem := newItem.DeepCopy() + err = insertItem.SetValue(newVal) + if err != nil { + return err + } + if insertAnn.IsBefore() { - updatedItems = append(updatedItems, newItem.DeepCopy()) + updatedItems = append(updatedItems, insertItem) } updatedItems = append(updatedItems, leftItem) if insertAnn.IsAfter() { - updatedItems = append(updatedItems, newItem.DeepCopy()) + updatedItems = append(updatedItems, insertItem) } break } diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/array_item_match_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/array_item_match_annotation.go similarity index 93% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/array_item_match_annotation.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/array_item_match_annotation.go index 41df874a9..41b62168f 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/array_item_match_annotation.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/array_item_match_annotation.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,12 +6,12 @@ package overlay import ( "fmt" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" ) type ArrayItemMatchAnnotation struct { diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/assert_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/assert_annotation.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/assert_annotation.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/assert_annotation.go index c3661fea0..06093e995 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/assert_annotation.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/assert_annotation.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,11 +6,11 @@ package overlay import ( "fmt" + "carvel.dev/ytt/pkg/template" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" ) type AssertAnnotation struct { diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/compare.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/compare.go similarity index 79% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/compare.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/compare.go index 9b3a0591b..c4b7d509b 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/compare.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/compare.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -7,7 +7,7 @@ import ( "fmt" "reflect" - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamlmeta" ) type Comparison struct{} @@ -15,20 +15,19 @@ type Comparison struct{} func (b Comparison) Compare(left, right interface{}) (bool, string) { switch typedRight := right.(type) { case *yamlmeta.DocumentSet: - panic("Unexpected docset") + panic(fmt.Sprintf("Unexpected %T", right)) case *yamlmeta.Document: typedLeft, isDoc := left.(*yamlmeta.Document) if !isDoc { - return false, fmt.Sprintf("Expected doc, but was %T", left) + return false, fmt.Sprintf("Expected document, but was %s", yamlmeta.TypeName(left)) } - return b.Compare(typedLeft.Value, typedRight.Value) case *yamlmeta.Map: typedLeft, isMap := left.(*yamlmeta.Map) if !isMap { - return false, fmt.Sprintf("Expected map, but was %T", left) + return false, fmt.Sprintf("Expected map, but was %s", yamlmeta.TypeName(left)) } for _, rightItem := range typedRight.Items { @@ -52,7 +51,7 @@ func (b Comparison) Compare(left, right interface{}) (bool, string) { case *yamlmeta.MapItem: typedLeft, isMapItem := left.(*yamlmeta.MapItem) if !isMapItem { - return false, fmt.Sprintf("Expected mapitem, but was %T", left) + return false, fmt.Sprintf("Expected map item, but was %s", yamlmeta.TypeName(left)) } return b.Compare(typedLeft.Value, typedRight.Value) @@ -60,7 +59,7 @@ func (b Comparison) Compare(left, right interface{}) (bool, string) { case *yamlmeta.Array: typedLeft, isArray := left.(*yamlmeta.Array) if !isArray { - return false, fmt.Sprintf("Expected array, but was %T", left) + return false, fmt.Sprintf("Expected array, but was %s", yamlmeta.TypeName(left)) } for i, item := range typedRight.Items { @@ -78,11 +77,9 @@ func (b Comparison) Compare(left, right interface{}) (bool, string) { case *yamlmeta.ArrayItem: typedLeft, isArrayItem := left.(*yamlmeta.ArrayItem) if !isArrayItem { - return false, fmt.Sprintf("Expected arrayitem, but was %T", left) + return false, fmt.Sprintf("Expected array item, but was %s", yamlmeta.TypeName(left)) } - return b.Compare(typedLeft.Value, typedRight.Value) - default: return b.CompareLeafs(left, right) } @@ -97,7 +94,7 @@ func (b Comparison) CompareLeafs(left, right interface{}) (bool, string) { return true, "" } - return false, fmt.Sprintf("Expected leaf values to match %T %T", left, right) + return false, fmt.Sprintf("Expected leaf values to match %s %s", yamlmeta.TypeName(left), yamlmeta.TypeName(right)) } func (b Comparison) compareAsInt64s(left, right interface{}) (bool, string) { diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/doc.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/doc.go new file mode 100644 index 000000000..5a388b4bd --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/doc.go @@ -0,0 +1,7 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +/* +Package overlay implements YAML patching via ytt annotations. +*/ +package overlay diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/document.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/document.go similarity index 90% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/document.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/document.go index a015ce4ad..cbf224199 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/document.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/document.go @@ -1,10 +1,12 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay import ( - "github.com/k14s/ytt/pkg/yamlmeta" + "fmt" + + "carvel.dev/ytt/pkg/yamlmeta" ) func (o Op) mergeDocument( @@ -119,7 +121,7 @@ func (o Op) replaceDocument( if len(leftIdxs) == 0 && replaceAnn.OrAdd() { if len(leftDocSets) == 0 { - panic("Internal inconsistency: Expected at least one doc set") + panic(fmt.Sprintf("Internal inconsistency: Expected at least one %T", &yamlmeta.DocumentSet{})) } newVal, err := replaceAnn.Value(nil) @@ -154,7 +156,7 @@ func (o Op) insertDocument( return err } - insertAnn, err := NewInsertAnnotation(newDoc) + insertAnn, err := NewInsertAnnotation(newDoc, o.Thread) if err != nil { return err } @@ -167,12 +169,23 @@ func (o Op) insertDocument( for _, leftIdx := range leftIdxs { if leftIdx[0] == i && leftIdx[1] == j { matched = true + + newVal, err := insertAnn.Value(leftItem) + if err != nil { + return err + } + insertDoc := newDoc.DeepCopy() + err = insertDoc.SetValue(newVal) + if err != nil { + return err + } + if insertAnn.IsBefore() { - updatedDocs = append(updatedDocs, newDoc.DeepCopy()) + updatedDocs = append(updatedDocs, insertDoc) } updatedDocs = append(updatedDocs, leftItem) if insertAnn.IsAfter() { - updatedDocs = append(updatedDocs, newDoc.DeepCopy()) + updatedDocs = append(updatedDocs, insertDoc) } break } diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/document_match_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/document_match_annotation.go similarity index 92% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/document_match_annotation.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/document_match_annotation.go index c25e6ee85..eec57da97 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/document_match_annotation.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/document_match_annotation.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,12 +6,12 @@ package overlay import ( "fmt" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" ) type DocumentMatchAnnotation struct { @@ -75,7 +75,7 @@ func (a DocumentMatchAnnotation) IndexTuples(leftDocSets []*yamlmeta.DocumentSet func (a DocumentMatchAnnotation) MatchNodes(leftDocSets []*yamlmeta.DocumentSet) ([][]int, []*filepos.Position, error) { if a.exact { if len(leftDocSets) != 1 && len(leftDocSets[0].Items) != 1 { - return nil, nil, fmt.Errorf("Expected to find exactly one left doc when merging exactly two documents") + return nil, nil, fmt.Errorf("Expected to find exactly one left document when merging exactly two documents") } return [][]int{{0, 0}}, []*filepos.Position{leftDocSets[0].Items[0].Position}, nil } diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/insert_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/insert_annotation.go new file mode 100644 index 000000000..a23de2116 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/insert_annotation.go @@ -0,0 +1,114 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package overlay + +import ( + "fmt" + + "carvel.dev/ytt/pkg/template" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamltemplate" + "github.com/k14s/starlark-go/starlark" +) + +// Kwargs of overlay/insert +const ( + InsertAnnotationKwargBefore string = "before" + InsertAnnotationKwargAfter string = "after" + InsertAnnotationKwargVia string = "via" +) + +type InsertAnnotation struct { + newItem template.EvaluationNode + before bool + after bool + via *starlark.Callable + thread *starlark.Thread +} + +// NewInsertAnnotation returns a new InsertAnnotation for the given node and with the given Starlark thread +func NewInsertAnnotation(newItem template.EvaluationNode, thread *starlark.Thread) (InsertAnnotation, error) { + annotation := InsertAnnotation{ + newItem: newItem, + thread: thread, + } + anns := template.NewAnnotations(newItem) + + if !anns.Has(AnnotationInsert) { + return annotation, fmt.Errorf( + "Expected item to have '%s' annotation", AnnotationInsert) + } + + kwargs := anns.Kwargs(AnnotationInsert) + if len(kwargs) == 0 { + return annotation, fmt.Errorf("Expected '%s' annotation to have "+ + "at least one keyword argument (before=..., after=...)", AnnotationInsert) + } + + for _, kwarg := range kwargs { + kwargName := string(kwarg[0].(starlark.String)) + + switch kwargName { + case InsertAnnotationKwargBefore: + resultBool, err := tplcore.NewStarlarkValue(kwarg[1]).AsBool() + if err != nil { + return InsertAnnotation{}, err + } + annotation.before = resultBool + + case InsertAnnotationKwargAfter: + resultBool, err := tplcore.NewStarlarkValue(kwarg[1]).AsBool() + if err != nil { + return InsertAnnotation{}, err + } + annotation.after = resultBool + + case InsertAnnotationKwargVia: + via, ok := kwarg[1].(starlark.Callable) + if !ok { + return InsertAnnotation{}, fmt.Errorf( + "Expected '%s' annotation keyword argument '%s' to be function, "+ + "but was %T", AnnotationInsert, kwargName, kwarg[1]) + } + annotation.via = &via + + default: + return annotation, fmt.Errorf( + "Unknown '%s' annotation keyword argument '%s'", AnnotationInsert, kwargName) + } + } + + return annotation, nil +} + +func (a InsertAnnotation) IsBefore() bool { return a.before } +func (a InsertAnnotation) IsAfter() bool { return a.after } + +// Value returns the new value for the given, existing node. If `via` is not provided, the value of the existing +// node is returned, otherwise the result of `via`. +func (a InsertAnnotation) Value(existingNode template.EvaluationNode) (interface{}, error) { + newNode := a.newItem.DeepCopyAsInterface().(template.EvaluationNode) + if a.via == nil { + return newNode.GetValues()[0], nil + } + + var existingVal interface{} + if existingNode != nil { + existingVal = existingNode.DeepCopyAsInterface().(template.EvaluationNode).GetValues()[0] + } else { + existingVal = nil + } + + viaArgs := starlark.Tuple{ + yamltemplate.NewGoValueWithYAML(existingVal).AsStarlarkValue(), + yamltemplate.NewGoValueWithYAML(newNode.GetValues()[0]).AsStarlarkValue(), + } + + result, err := starlark.Call(a.thread, *a.via, viaArgs, []starlark.Tuple{}) + if err != nil { + return nil, err + } + + return tplcore.NewStarlarkValue(result).AsGoValue() +} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/map.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/map.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/map.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/map.go index b9c592b5f..109165cc4 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/map.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/map.go @@ -1,10 +1,10 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay import ( - "github.com/k14s/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamlmeta" ) func (o Op) mergeMapItem(leftMap *yamlmeta.Map, newItem *yamlmeta.MapItem, diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/map_item_match_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/map_item_match_annotation.go similarity index 93% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/map_item_match_annotation.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/map_item_match_annotation.go index b0c9923cf..b6b3b03fc 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/map_item_match_annotation.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/map_item_match_annotation.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -7,12 +7,12 @@ import ( "fmt" "reflect" + "carvel.dev/ytt/pkg/filepos" + "carvel.dev/ytt/pkg/template" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" ) type MapItemMatchAnnotation struct { diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/match_annotation_expects_kwarg.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/match_annotation_expects_kwarg.go similarity index 98% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/match_annotation_expects_kwarg.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/match_annotation_expects_kwarg.go index f80f0d8a7..94a22a2eb 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/match_annotation_expects_kwarg.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/match_annotation_expects_kwarg.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -9,8 +9,8 @@ import ( "strconv" "strings" + "carvel.dev/ytt/pkg/filepos" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/filepos" ) const ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/match_child_defaults_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/match_child_defaults_annotation.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/match_child_defaults_annotation.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/match_child_defaults_annotation.go index 95dbf7215..35780769a 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/match_child_defaults_annotation.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/match_child_defaults_annotation.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,8 +6,8 @@ package overlay import ( "fmt" + "carvel.dev/ytt/pkg/template" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" ) type MatchChildDefaultsAnnotation struct { diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/op.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/op.go similarity index 87% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/op.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/op.go index 3c4d2f869..1e0ef76a1 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/op.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/op.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,9 +6,9 @@ package overlay import ( "fmt" + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" ) type Op struct { @@ -45,7 +45,7 @@ func (o Op) apply(left, right interface{}, parentMatchChildDefaults MatchChildDe // (see matching for overlay post processing) typedLeft, isDocSetArray := left.([]*yamlmeta.DocumentSet) if !isDocSetArray { - return false, fmt.Errorf("Expected docset, but was %T", left) + return false, fmt.Errorf("Expected document set, but was %s", yamlmeta.TypeName(left)) } docSetArray = typedLeft } else { @@ -54,13 +54,10 @@ func (o Op) apply(left, right interface{}, parentMatchChildDefaults MatchChildDe return o.applyDocSet(docSetArray, typedRight, parentMatchChildDefaults) - case *yamlmeta.Document: - panic("Unexpected doc") - case *yamlmeta.Map: typedLeft, isMap := left.(*yamlmeta.Map) if !isMap { - return false, fmt.Errorf("Expected map, but was %T", left) + return false, fmt.Errorf("Expected map, but was %s", yamlmeta.TypeName(left)) } for _, item := range typedRight.Items { @@ -78,7 +75,7 @@ func (o Op) apply(left, right interface{}, parentMatchChildDefaults MatchChildDe case AnnotationAssert: err = o.assertMapItem(typedLeft, item, parentMatchChildDefaults) default: - err = fmt.Errorf("Overlay op %s is not supported on map item", op) + err = fmt.Errorf("Found @%s on map item (%s); only array items can be annotated with @%s", op, item.GetPosition().AsCompactString(), op) } } if err != nil { @@ -87,13 +84,10 @@ func (o Op) apply(left, right interface{}, parentMatchChildDefaults MatchChildDe } } - case *yamlmeta.MapItem: - panic("Unexpected mapitem") - case *yamlmeta.Array: typedLeft, isArray := left.(*yamlmeta.Array) if !isArray { - return false, fmt.Errorf("Expected array, but was %T", left) + return false, fmt.Errorf("Expected array, but was %s", yamlmeta.TypeName(left)) } for _, item := range typedRight.Items { @@ -123,8 +117,8 @@ func (o Op) apply(left, right interface{}, parentMatchChildDefaults MatchChildDe } } - case *yamlmeta.ArrayItem: - panic("Unexpected arrayitem") + case *yamlmeta.Document, *yamlmeta.MapItem, *yamlmeta.ArrayItem: + panic(fmt.Sprintf("Unexpected %T", right)) default: return true, nil diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/plain_merge.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/plain_merge.go new file mode 100644 index 000000000..6842ee968 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/plain_merge.go @@ -0,0 +1,58 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package overlay + +import ( + "fmt" + + "carvel.dev/ytt/pkg/template" + "carvel.dev/ytt/pkg/yamlmeta" + "carvel.dev/ytt/pkg/yamltemplate" + "github.com/k14s/starlark-go/starlark" +) + +// AnnotateForPlainMerge configures `node` to be an overlay doing a "plain merge": +// - allow new keys via `@overlay/match missing_ok=True` +// - allow arrays and scalars to be replaced with given value (regardless of type) via `@overlay/replace or_add=True` +// +// Returns an error when `node` contains templating; `node` must be plain YAML. +func AnnotateForPlainMerge(node yamlmeta.Node) error { + if yamltemplate.HasTemplating(node) { + return fmt.Errorf("Expected to be plain YAML, having no annotations (hint: remove comments starting with `#@`)") + } + + addOverlayReplace(node) + return nil +} + +func addOverlayReplace(node yamlmeta.Node) { + anns := template.NodeAnnotations{} + + anns[AnnotationMatch] = template.NodeAnnotation{ + Kwargs: []starlark.Tuple{{ + starlark.String(MatchAnnotationKwargMissingOK), + starlark.Bool(true), + }}, + } + + replaceAnn := template.NodeAnnotation{ + Kwargs: []starlark.Tuple{{ + starlark.String(ReplaceAnnotationKwargOrAdd), + starlark.Bool(true), + }}, + } + + for _, val := range node.GetValues() { + switch typedVal := val.(type) { + case *yamlmeta.Array: + anns[AnnotationReplace] = replaceAnn + case yamlmeta.Node: + addOverlayReplace(typedVal) + default: + anns[AnnotationReplace] = replaceAnn + } + } + + node.SetAnnotations(anns) +} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/replace_annotation.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/replace_annotation.go similarity index 58% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/replace_annotation.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/replace_annotation.go index 9a09aac40..cddecb808 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/replace_annotation.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/overlay/replace_annotation.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package overlay @@ -6,10 +6,10 @@ package overlay import ( "fmt" + "carvel.dev/ytt/pkg/template" + tplcore "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamltemplate" "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamltemplate" ) const ( @@ -20,7 +20,7 @@ const ( type ReplaceAnnotation struct { newNode template.EvaluationNode thread *starlark.Thread - via *starlark.Value + via *starlark.Callable orAdd bool } @@ -36,7 +36,13 @@ func NewReplaceAnnotation(newNode template.EvaluationNode, thread *starlark.Thre switch kwargName { case ReplaceAnnotationKwargVia: - annotation.via = &kwarg[1] + via, ok := kwarg[1].(starlark.Callable) + if !ok { + return ReplaceAnnotation{}, fmt.Errorf( + "Expected '%s' annotation keyword argument '%s' to be function, "+ + "but was %T", AnnotationReplace, kwargName, kwarg[1]) + } + annotation.via = &via case ReplaceAnnotationKwargOrAdd: resultBool, err := tplcore.NewStarlarkValue(kwarg[1]).AsBool() @@ -63,33 +69,26 @@ func (a ReplaceAnnotation) Value(existingNode template.EvaluationNode) (interfac return newNode.GetValues()[0], nil } - switch typedVal := (*a.via).(type) { - case starlark.Callable: - var existingVal interface{} - if existingNode != nil { - // Make sure original nodes are not affected in any way - existingVal = existingNode.DeepCopyAsInterface().(template.EvaluationNode).GetValues()[0] - } else { - existingVal = nil - } - - viaArgs := starlark.Tuple{ - yamltemplate.NewGoValueWithYAML(existingVal).AsStarlarkValue(), - yamltemplate.NewGoValueWithYAML(newNode.GetValues()[0]).AsStarlarkValue(), - } - - // TODO check thread correctness - result, err := starlark.Call(a.thread, *a.via, viaArgs, []starlark.Tuple{}) - if err != nil { - return nil, err - } + var existingVal interface{} + if existingNode != nil { + // Make sure original nodes are not affected in any way + existingVal = existingNode.DeepCopyAsInterface().(template.EvaluationNode).GetValues()[0] + } else { + existingVal = nil + } - return tplcore.NewStarlarkValue(result).AsGoValue() + viaArgs := starlark.Tuple{ + yamltemplate.NewGoValueWithYAML(existingVal).AsStarlarkValue(), + yamltemplate.NewGoValueWithYAML(newNode.GetValues()[0]).AsStarlarkValue(), + } - default: - return nil, fmt.Errorf("Expected '%s' annotation keyword argument 'via'"+ - " to be function, but was %T", AnnotationReplace, typedVal) + // TODO check thread correctness + result, err := starlark.Call(a.thread, *a.via, viaArgs, []starlark.Tuple{}) + if err != nil { + return nil, err } + + return tplcore.NewStarlarkValue(result).AsGoValue() } func (a ReplaceAnnotation) OrAdd() bool { return a.orAdd } diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/regexp.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/regexp.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/regexp.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/regexp.go index b901c7733..e7a841b2d 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/regexp.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/regexp.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -7,9 +7,9 @@ import ( "fmt" "regexp" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" ) var ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/sha256.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/sha256.go similarity index 92% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/sha256.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/sha256.go index 6e935971c..dd0806057 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/sha256.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/sha256.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -7,9 +7,9 @@ import ( "crypto/sha256" "fmt" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" ) var ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/struct.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/struct.go similarity index 97% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/struct.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/struct.go index 6156a07a9..da3b10c88 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/struct.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/struct.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -6,10 +6,10 @@ package yttlibrary import ( "fmt" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/orderedmap" - "github.com/k14s/ytt/pkg/template/core" ) var ( diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/template.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/template.go similarity index 89% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/template.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/template.go index df09002ce..8f1755da5 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/template.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/template.go @@ -1,12 +1,12 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary import ( + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" ) type TemplateModule struct { diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/url.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/url.go similarity index 82% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/url.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/url.go index d6454535c..d6ff14534 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/url.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/url.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -7,11 +7,12 @@ import ( "fmt" "net/url" "sort" + "strings" + "carvel.dev/ytt/pkg/orderedmap" + "carvel.dev/ytt/pkg/template/core" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/orderedmap" - "github.com/k14s/ytt/pkg/template/core" ) var ( @@ -169,6 +170,7 @@ func (b urlModule) QueryParamsDecode(thread *starlark.Thread, f *starlark.Builti return starlark.None, err } + encodedVal = b.allowQuerySemicolons(encodedVal) urlVals, err := url.ParseQuery(encodedVal) if err != nil { return starlark.None, err @@ -187,6 +189,19 @@ func (b urlModule) QueryParamsDecode(thread *starlark.Thread, f *starlark.Builti return core.NewGoValue(result).AsStarlarkValue(), nil } +// allowQuerySemicolons restores pre-Go 1.17 handling of query parameters. +// Doing so defers making a breaking change as we upgrade from Go 1.16 to 1.17. +// We expect to pass along this breaking change to end-users at some point, but not at this time (circa v0.37.x). +// Shamelessly stolen from https://cs.opensource.google/go/go/+/refs/tags/go1.17.2:src/net/http/server.go;l=2892-2908 +// See also: +// - https://golang.org/doc/go1.17#semicolons +// - https://github.com/golang/go/issues/25192 +// - particularly https://github.com/golang/go/issues/25192#issuecomment-789799446 which spells-out the vulnerability +// specifically. +func (b urlModule) allowQuerySemicolons(encodedVal string) string { + return strings.ReplaceAll(encodedVal, ";", "&") +} + func (b urlModule) sortedKeys(vals url.Values) []string { var result []string for k := range vals { @@ -214,20 +229,23 @@ func (b urlModule) ParseURL(thread *starlark.Thread, f *starlark.Builtin, args s return (&URLValue{parsedURL, nil}).AsStarlarkValue(), nil } -func (uv *URLValue) Type() string { return "@ytt:url.value" } +const urlValueTypeName = "url.value" + +// Type reports the fully-qualified name of type of this custom struct. +func (uv *URLValue) Type() string { return "@ytt:" + urlValueTypeName } func (uv *URLValue) AsStarlarkValue() starlark.Value { m := orderedmap.NewMap() m.Set("user", uv.User()) - m.Set("without_user", starlark.NewBuiltin("url.without_user", core.ErrWrapper(uv.WithoutUser))) - m.Set("string", starlark.NewBuiltin("url.string", core.ErrWrapper(uv.string))) - m.Set("hostname", starlark.NewBuiltin("url.hostname", core.ErrWrapper(uv.Hostname))) + m.Set("without_user", starlark.NewBuiltin(urlValueTypeName+".without_user", core.ErrWrapper(uv.WithoutUser))) + m.Set("string", starlark.NewBuiltin(urlValueTypeName+".string", core.ErrWrapper(uv.string))) + m.Set("hostname", starlark.NewBuiltin(urlValueTypeName+".hostname", core.ErrWrapper(uv.Hostname))) uv.StarlarkStruct = core.NewStarlarkStruct(m) return uv } func (uv *URLValue) ConversionHint() string { - return "URLValue does not automatically encode (hint: use .string())" + return uv.Type() + " does not automatically encode (hint: use .string())" } func (uv *URLValue) Hostname(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { @@ -258,10 +276,13 @@ func (uv *URLValue) User() starlark.Value { return uu } -func (uu *URLUser) Type() string { return "@ytt:url.user" } +const urlUserTypeName = "url.user" + +// Type reports the fully-qualified name of type of this custom struct. +func (uu *URLUser) Type() string { return "@ytt:" + urlUserTypeName } func (uu *URLUser) ConversionHint() string { - return "URLUser does not automatically encode (hint: use .string())" + return uu.Type() + " does not automatically encode (hint: use .string())" } func (uu *URLUser) password() starlark.Value { diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/version.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/version.go similarity index 94% rename from vendor/github.com/k14s/ytt/pkg/yttlibrary/version.go rename to vendor/carvel.dev/ytt/pkg/yttlibrary/version.go index 71b04941d..d2ba1ecbe 100644 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/version.go +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/version.go @@ -1,4 +1,4 @@ -// Copyright 2020 VMware, Inc. +// Copyright 2024 The Carvel Authors. // SPDX-License-Identifier: Apache-2.0 package yttlibrary @@ -7,11 +7,11 @@ import ( "fmt" "regexp" + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/version" semver "github.com/hashicorp/go-version" "github.com/k14s/starlark-go/starlark" "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/version" ) const ( diff --git a/vendor/carvel.dev/ytt/pkg/yttlibrary/yaml.go b/vendor/carvel.dev/ytt/pkg/yttlibrary/yaml.go new file mode 100644 index 000000000..3eab7d671 --- /dev/null +++ b/vendor/carvel.dev/ytt/pkg/yttlibrary/yaml.go @@ -0,0 +1,100 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package yttlibrary + +import ( + "fmt" + + "carvel.dev/ytt/pkg/template/core" + "carvel.dev/ytt/pkg/yamlmeta" + "github.com/k14s/starlark-go/starlark" + "github.com/k14s/starlark-go/starlarkstruct" +) + +var ( + // YAMLAPI contains the definition of the @ytt:yaml module + YAMLAPI = starlark.StringDict{ + "yaml": &starlarkstruct.Module{ + Name: "yaml", + Members: starlark.StringDict{ + "encode": starlark.NewBuiltin("yaml.encode", core.ErrWrapper(yamlModule{}.starlarkEncode)), + "decode": starlark.NewBuiltin("yaml.decode", core.ErrWrapper(yamlModule{}.starlarkDecode)), + }, + }, + } +) + +type yamlModule struct{} + +// starlarkEncode adapts a call from Starlark to yamlModule.Encode() +func (b yamlModule) starlarkEncode(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("expected exactly one argument") + } + + val, err := core.NewStarlarkValue(args.Index(0)).AsGoValue() + if err != nil { + return starlark.None, err + } + + encoded, err := b.Encode(val) + if err != nil { + return starlark.None, nil + } + + return starlark.String(encoded), nil +} + +// Encode renders the provided input as a YAML-formatted string +func (b yamlModule) Encode(goValue interface{}) (string, error) { + var docSet *yamlmeta.DocumentSet + + switch typedVal := goValue.(type) { + case *yamlmeta.DocumentSet: + docSet = typedVal + case *yamlmeta.Document: + // Documents should be part of DocumentSet by the time it makes it here + panic("Unexpected document") + default: + docSet = &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{{Value: typedVal}}} + } + + valBs, err := docSet.AsBytes() + if err != nil { + return "", err + } + + return string(valBs), nil +} + +// Decode is a core.StarlarkFunc that parses the provided input from YAML format into dicts, lists, and scalars +func (b yamlModule) starlarkDecode(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) { + if args.Len() != 1 { + return starlark.None, fmt.Errorf("expected exactly one argument") + } + + valEncoded, err := core.NewStarlarkValue(args.Index(0)).AsString() + if err != nil { + return starlark.None, err + } + + value, err := b.Decode(valEncoded) + if err != nil { + return nil, err + } + + return value, nil +} + +func (b yamlModule) Decode(yamlString string) (starlark.Value, error) { + var decoded interface{} + + err := yamlmeta.PlainUnmarshal([]byte(yamlString), &decoded) + if err != nil { + return starlark.None, err + } + + value := core.NewGoValue(decoded).AsStarlarkValue() + return value, nil +} diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/template/data_values_file.go b/vendor/github.com/k14s/ytt/pkg/cmd/template/data_values_file.go deleted file mode 100644 index 2f3b8e7c6..000000000 --- a/vendor/github.com/k14s/ytt/pkg/cmd/template/data_values_file.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package template - -import ( - "fmt" - - "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/k14s/ytt/pkg/yamltemplate" - yttoverlay "github.com/k14s/ytt/pkg/yttlibrary/overlay" -) - -type DataValuesFile struct { - doc *yamlmeta.Document -} - -func NewDataValuesFile(doc *yamlmeta.Document) DataValuesFile { - return DataValuesFile{doc.DeepCopy()} -} - -func (f DataValuesFile) AsOverlay() (*yamlmeta.Document, error) { - doc := f.doc.DeepCopy() - - if yamltemplate.HasTemplating(doc) { - return nil, fmt.Errorf("Expected to not find annotations inside data values file " + - "(hint: remove comments starting with '#@')") - } - - f.addOverlayReplace(doc) - - return doc, nil -} - -func (f DataValuesFile) addOverlayReplace(node yamlmeta.Node) { - anns := template.NodeAnnotations{ - yttoverlay.AnnotationMatch: template.NodeAnnotation{ - Kwargs: []starlark.Tuple{{ - starlark.String(yttoverlay.MatchAnnotationKwargMissingOK), - starlark.Bool(true), - }}, - }, - } - - replaceAnn := template.NodeAnnotation{ - Kwargs: []starlark.Tuple{{ - starlark.String(yttoverlay.ReplaceAnnotationKwargOrAdd), - starlark.Bool(true), - }}, - } - - for _, val := range node.GetValues() { - switch typedVal := val.(type) { - case *yamlmeta.Array: - anns[yttoverlay.AnnotationReplace] = replaceAnn - case yamlmeta.Node: - f.addOverlayReplace(typedVal) - default: - anns[yttoverlay.AnnotationReplace] = replaceAnn - } - } - - node.SetAnnotations(anns) -} diff --git a/vendor/github.com/k14s/ytt/pkg/cmd/template/regular_input.go b/vendor/github.com/k14s/ytt/pkg/cmd/template/regular_input.go deleted file mode 100644 index 219e2328a..000000000 --- a/vendor/github.com/k14s/ytt/pkg/cmd/template/regular_input.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package template - -import ( - "fmt" - "io" - - "github.com/k14s/ytt/pkg/cmd/ui" - "github.com/k14s/ytt/pkg/files" - "github.com/k14s/ytt/pkg/yamlmeta" - "github.com/spf13/cobra" -) - -const ( - regularFilesOutputTypeYAML = "yaml" - regularFilesOutputTypeJSON = "json" - regularFilesOutputTypePos = "pos" -) - -type RegularFilesSourceOpts struct { - files []string - - outputDir string - OutputFiles string - OutputType string - - files.SymlinkAllowOpts -} - -func (s *RegularFilesSourceOpts) Set(cmd *cobra.Command) { - cmd.Flags().StringArrayVarP(&s.files, "file", "f", nil, "File (ie local path, HTTP URL, -) (can be specified multiple times)") - - cmd.Flags().StringVar(&s.outputDir, "dangerous-emptied-output-directory", "", - "Delete given directory, and then create it with output files") - cmd.Flags().StringVar(&s.OutputFiles, "output-files", "", "Add output files to given directory") - - cmd.Flags().StringVarP(&s.OutputType, "output", "o", regularFilesOutputTypeYAML, "Output type (yaml, json, pos)") - - cmd.Flags().BoolVar(&s.SymlinkAllowOpts.AllowAll, "dangerous-allow-all-symlink-destinations", false, - "Symlinks to all destinations are allowed") - cmd.Flags().StringSliceVar(&s.SymlinkAllowOpts.AllowedDstPaths, "allow-symlink-destination", nil, - "File paths to which symlinks are allowed (can be specified multiple times)") -} - -type RegularFilesSource struct { - opts RegularFilesSourceOpts - ui ui.UI -} - -func NewRegularFilesSource(opts RegularFilesSourceOpts, ui ui.UI) *RegularFilesSource { - return &RegularFilesSource{opts, ui} -} - -func (s *RegularFilesSource) HasInput() bool { return len(s.opts.files) > 0 } -func (s *RegularFilesSource) HasOutput() bool { return true } - -func (s *RegularFilesSource) Input() (Input, error) { - filesToProcess, err := files.NewSortedFilesFromPaths(s.opts.files, s.opts.SymlinkAllowOpts) - if err != nil { - return Input{}, err - } - - return Input{Files: filesToProcess}, nil -} - -func (s *RegularFilesSource) Output(out Output) error { - if out.Err != nil { - return out.Err - } - - nonYamlFileNames := []string{} - switch { - case len(s.opts.outputDir) > 0: - return files.NewOutputDirectory(s.opts.outputDir, out.Files, s.ui).Write() - case len(s.opts.OutputFiles) > 0: - return files.NewOutputDirectory(s.opts.OutputFiles, out.Files, s.ui).WriteFiles() - default: - for _, file := range out.Files { - if file.Type() != files.TypeYAML { - nonYamlFileNames = append(nonYamlFileNames, file.RelativePath()) - } - } - } - - var printerFunc func(io.Writer) yamlmeta.DocumentPrinter - - switch s.opts.OutputType { - case regularFilesOutputTypeYAML: - printerFunc = nil - case regularFilesOutputTypeJSON: - printerFunc = func(w io.Writer) yamlmeta.DocumentPrinter { return yamlmeta.NewJSONPrinter(w) } - case regularFilesOutputTypePos: - printerFunc = func(w io.Writer) yamlmeta.DocumentPrinter { - return yamlmeta.WrappedFilePositionPrinter{yamlmeta.NewFilePositionPrinter(w)} - } - default: - return fmt.Errorf("Unknown output type '%s'", s.opts.OutputType) - } - - combinedDocBytes, err := out.DocSet.AsBytesWithPrinter(printerFunc) - if err != nil { - return fmt.Errorf("Marshaling combined template result: %s", err) - } - - s.ui.Debugf("### result\n") - s.ui.Printf("%s", combinedDocBytes) // no newline - - if len(nonYamlFileNames) > 0 { - s.ui.Warnf("\n" + `Warning: Found Non-YAML templates in input. Non-YAML templates are not rendered to standard output. -If you want to include those results, use the --output-files or --dangerous-emptied-output-directory flag.` + "\n") - } - return nil -} diff --git a/vendor/github.com/k14s/ytt/pkg/schema/annotations.go b/vendor/github.com/k14s/ytt/pkg/schema/annotations.go deleted file mode 100644 index 46ded47e5..000000000 --- a/vendor/github.com/k14s/ytt/pkg/schema/annotations.go +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2021 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package schema - -import ( - "fmt" - "sort" - - "github.com/k14s/ytt/pkg/filepos" - - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -const ( - AnnotationNullable template.AnnotationName = "schema/nullable" - AnnotationType template.AnnotationName = "schema/type" - TypeAnnotationKwargAny string = "any" -) - -type Annotation interface { - NewTypeFromAnn() yamlmeta.Type -} - -type TypeAnnotation struct { - any bool - inferredType yamlmeta.Type - itemPosition *filepos.Position -} - -type NullableAnnotation struct { - providedValueType yamlmeta.Type - itemPosition *filepos.Position -} - -func NewTypeAnnotation(ann template.NodeAnnotation, inferredType yamlmeta.Type, pos *filepos.Position) (*TypeAnnotation, error) { - if len(ann.Kwargs) == 0 { - return nil, schemaAssertionError{ - position: pos, - description: fmt.Sprintf("expected @%v annotation to have keyword argument and value", AnnotationType), - expected: "valid keyword argument and value", - found: "missing keyword argument and value", - hints: []string{fmt.Sprintf("Supported key-value pairs are '%v=True', '%v=False'", TypeAnnotationKwargAny, TypeAnnotationKwargAny)}, - } - } - typeAnn := &TypeAnnotation{inferredType: inferredType, itemPosition: pos} - for _, kwarg := range ann.Kwargs { - argName, err := core.NewStarlarkValue(kwarg[0]).AsString() - if err != nil { - return nil, err - } - - switch argName { - case TypeAnnotationKwargAny: - isAnyType, err := core.NewStarlarkValue(kwarg[1]).AsBool() - if err != nil { - return nil, schemaAssertionError{ - position: pos, - description: "unknown @schema/type annotation keyword argument", - expected: "starlark.Bool", - found: fmt.Sprintf("%T", kwarg[1]), - hints: []string{fmt.Sprintf("Supported kwargs are '%v'", TypeAnnotationKwargAny)}, - } - } - typeAnn.any = isAnyType - - default: - return nil, schemaAssertionError{ - position: pos, - description: "unknown @schema/type annotation keyword argument", - expected: "A valid kwarg", - found: argName, - hints: []string{fmt.Sprintf("Supported kwargs are '%v'", TypeAnnotationKwargAny)}, - } - } - } - return typeAnn, nil -} - -func NewNullableAnnotation(ann template.NodeAnnotation, valueType yamlmeta.Type, pos *filepos.Position) (*NullableAnnotation, error) { - if len(ann.Kwargs) != 0 { - return nil, fmt.Errorf("expected @%v annotation to not contain any keyword arguments", AnnotationNullable) - } - - return &NullableAnnotation{valueType, pos}, nil -} - -func (t *TypeAnnotation) NewTypeFromAnn() yamlmeta.Type { - if t.any { - return &AnyType{ValueType: t.inferredType, Position: t.itemPosition} - } - return nil -} - -func (t *TypeAnnotation) IsAny() bool { - return t.any -} - -func (n *NullableAnnotation) NewTypeFromAnn() yamlmeta.Type { - return &NullType{ValueType: n.providedValueType, Position: n.itemPosition} -} - -func collectAnnotations(item yamlmeta.Node) ([]Annotation, error) { - var anns []Annotation - - for _, annotation := range []template.AnnotationName{AnnotationType, AnnotationNullable} { - ann, err := processOptionalAnnotation(item, annotation) - if err != nil { - return nil, err - } - if ann != nil { - anns = append(anns, ann) - } - } - return anns, nil -} - -func processOptionalAnnotation(node yamlmeta.Node, optionalAnnotation template.AnnotationName) (Annotation, error) { - nodeAnnotations := template.NewAnnotations(node) - - if nodeAnnotations.Has(optionalAnnotation) { - ann, _ := nodeAnnotations[optionalAnnotation] - - wrappedValueType, err := inferTypeFromValue(node.GetValues()[0], node.GetPosition()) - if err != nil { - return nil, err - } - - switch optionalAnnotation { - case AnnotationNullable: - nullAnn, err := NewNullableAnnotation(ann, wrappedValueType, node.GetPosition()) - if err != nil { - return nil, err - } - return nullAnn, nil - case AnnotationType: - typeAnn, err := NewTypeAnnotation(ann, wrappedValueType, node.GetPosition()) - if err != nil { - return nil, err - } - return typeAnn, nil - } - } - - return nil, nil -} - -func getTypeFromAnnotations(anns []Annotation) yamlmeta.Type { - annsCopy := append([]Annotation{}, anns...) - - if len(annsCopy) == 0 { - return nil - } - - // allow Configuration Author to annotate "nullable" as a fallback if "any" is false. - preferAnyTypeOverNullableType := func(i, j int) bool { - if typeAnn, ok := annsCopy[i].(*TypeAnnotation); ok && typeAnn.IsAny() { - return true - } - return false - } - - sort.Slice(annsCopy, preferAnyTypeOverNullableType) - return annsCopy[0].NewTypeFromAnn() -} diff --git a/vendor/github.com/k14s/ytt/pkg/schema/schema.go b/vendor/github.com/k14s/ytt/pkg/schema/schema.go deleted file mode 100644 index 338dcdd68..000000000 --- a/vendor/github.com/k14s/ytt/pkg/schema/schema.go +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package schema - -import ( - "fmt" - "strings" - - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/workspace/ref" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -type DocumentSchema struct { - Source *yamlmeta.Document - defaultDVs *yamlmeta.Document - DocType yamlmeta.Type -} - -type DocumentSchemaEnvelope struct { - Doc *DocumentSchema - - used bool - originalLibRef []ref.LibraryRef - libRef []ref.LibraryRef -} - -func NewDocumentSchema(doc *yamlmeta.Document) (*DocumentSchema, error) { - docType, err := inferTypeFromValue(doc, doc.Position) - if err != nil { - return nil, err - } - - schemaDVs := docType.GetDefaultValue() - - return &DocumentSchema{ - Source: doc, - defaultDVs: schemaDVs.(*yamlmeta.Document), - DocType: docType, - }, nil -} - -func NewDocumentSchemaEnvelope(doc *yamlmeta.Document) (*DocumentSchemaEnvelope, error) { - libRef, err := getSchemaLibRef(ref.LibraryRefExtractor{}, doc) - if err != nil { - return nil, err - } - - schema, err := NewDocumentSchema(doc) - if err != nil { - return nil, err - } - - return &DocumentSchemaEnvelope{ - Doc: schema, - originalLibRef: libRef, - libRef: libRef, - }, nil -} - -// NewNullSchema provides the "Null Object" value of Schema. This is used in the case where no schema was provided. -func NewNullSchema() *DocumentSchema { - return &DocumentSchema{ - Source: &yamlmeta.Document{}, - DocType: &DocumentType{ - ValueType: &AnyType{}}, - } -} - -func NewDocumentType(doc *yamlmeta.Document) (*DocumentType, error) { - typeOfValue, err := getType(doc) - if err != nil { - return nil, err - } - - return &DocumentType{Source: doc, Position: doc.Position, ValueType: typeOfValue, defaultValue: typeOfValue.GetDefaultValue()}, nil -} - -func NewMapType(m *yamlmeta.Map) (*MapType, error) { - mapType := &MapType{Position: m.Position} - - for _, mapItem := range m.Items { - mapItemType, err := NewMapItemType(mapItem) - if err != nil { - return nil, err - } - mapType.Items = append(mapType.Items, mapItemType) - } - - return mapType, nil -} - -func NewMapItemType(item *yamlmeta.MapItem) (*MapItemType, error) { - typeOfValue, err := getType(item) - if err != nil { - return nil, err - } - - return &MapItemType{Key: item.Key, ValueType: typeOfValue, defaultValue: typeOfValue.GetDefaultValue(), Position: item.Position}, nil -} - -func NewArrayType(a *yamlmeta.Array) (*ArrayType, error) { - if len(a.Items) != 1 { - return nil, NewSchemaError("Invalid schema - wrong number of items in array definition", schemaAssertionError{ - position: a.Position, - expected: "exactly 1 array item, of the desired type", - found: fmt.Sprintf("%d array items", len(a.Items)), - hints: []string{"in schema, the one item of the array implies the type of its elements.", "in schema, the default value for an array is always an empty list.", "default values can be overridden via a data values overlay."}, - }) - } - - arrayItemType, err := NewArrayItemType(a.Items[0]) - if err != nil { - return nil, err - } - - return &ArrayType{ItemsType: arrayItemType, defaultValue: &yamlmeta.Array{}, Position: a.Position}, nil -} - -func NewArrayItemType(item *yamlmeta.ArrayItem) (*ArrayItemType, error) { - typeOfValue, err := getType(item) - if err != nil { - return nil, err - } - - return &ArrayItemType{ValueType: typeOfValue, defaultValue: typeOfValue.GetDefaultValue(), Position: item.GetPosition()}, nil -} - -func getType(node yamlmeta.ValueHoldingNode) (yamlmeta.Type, error) { - var typeOfValue yamlmeta.Type - - anns, err := collectAnnotations(node) - if err != nil { - return nil, NewSchemaError("Invalid schema", err) - } - typeOfValue = getTypeFromAnnotations(anns) - - if typeOfValue == nil { - typeOfValue, err = inferTypeFromValue(node.Val(), node.GetPosition()) - if err != nil { - return nil, err - } - } - - err = valueTypeAllowsItemValue(typeOfValue, node.Val(), node.GetPosition()) - if err != nil { - return nil, err - } - - return typeOfValue, nil -} - -func inferTypeFromValue(value interface{}, position *filepos.Position) (yamlmeta.Type, error) { - switch typedContent := value.(type) { - case *yamlmeta.Document: - docType, err := NewDocumentType(typedContent) - if err != nil { - return nil, err - } - return docType, nil - case *yamlmeta.Map: - mapType, err := NewMapType(typedContent) - if err != nil { - return nil, err - } - return mapType, nil - case *yamlmeta.Array: - arrayType, err := NewArrayType(typedContent) - if err != nil { - return nil, err - } - return arrayType, nil - case string: - return &ScalarType{ValueType: *new(string), defaultValue: typedContent, Position: position}, nil - case float64: - return &ScalarType{ValueType: *new(float64), defaultValue: typedContent, Position: position}, nil - case int, int64, uint64: - return &ScalarType{ValueType: *new(int), defaultValue: typedContent, Position: position}, nil - case bool: - return &ScalarType{ValueType: *new(bool), defaultValue: typedContent, Position: position}, nil - case nil: - return nil, nil - } - - return nil, fmt.Errorf("Expected value '%s' to be a map, array, or scalar, but was %T", value, value) -} - -func valueTypeAllowsItemValue(explicitType yamlmeta.Type, itemValue interface{}, position *filepos.Position) error { - switch explicitType.(type) { - case *AnyType: - return nil - default: - if itemValue == nil { - return NewSchemaError("Invalid schema - null value not allowed here", schemaAssertionError{ - position: position, - expected: "non-null value", - found: "null value", - hints: []string{"in YAML, omitting a value implies null.", "to set the default value to null, annotate with @schema/nullable.", "to allow any value, annotate with @schema/type any=True."}, - }) - } - } - return nil -} - -type ExtractLibRefs interface { - FromAnnotation(template.NodeAnnotations) ([]ref.LibraryRef, error) -} - -func getSchemaLibRef(libRefs ExtractLibRefs, doc *yamlmeta.Document) ([]ref.LibraryRef, error) { - anns := template.NewAnnotations(doc) - libRef, err := libRefs.FromAnnotation(anns) - if err != nil { - return nil, err - } - return libRef, nil -} - -func (s *DocumentSchema) AssignType(typeable yamlmeta.Typeable) yamlmeta.TypeCheck { - return s.DocType.AssignTypeTo(typeable) -} - -func (s *DocumentSchema) DefaultDataValues() *yamlmeta.Document { - return s.defaultDVs -} - -func (s *DocumentSchema) deepCopy() *DocumentSchema { - return &DocumentSchema{ - Source: s.Source.DeepCopy(), - defaultDVs: s.defaultDVs.DeepCopy(), - DocType: s.DocType, - } -} - -func (s *DocumentSchema) ValidateWithValues(valuesFilesCount int) error { - return nil -} - -func (e *DocumentSchemaEnvelope) Source() *yamlmeta.Document { - return e.Doc.Source -} - -func (e *DocumentSchemaEnvelope) Desc() string { - var desc []string - for _, refPiece := range e.originalLibRef { - desc = append(desc, refPiece.AsString()) - } - return fmt.Sprintf("Schema belonging to library '%s%s' on %s", "@", - strings.Join(desc, "@"), e.Source().Position.AsString()) -} - -func (e *DocumentSchemaEnvelope) IsUsed() bool { return e.used } - -func (e *DocumentSchemaEnvelope) IntendedForAnotherLibrary() bool { - return len(e.libRef) > 0 -} - -func (e *DocumentSchemaEnvelope) UsedInLibrary(expectedRefPiece ref.LibraryRef) (*DocumentSchemaEnvelope, bool) { - if !e.IntendedForAnotherLibrary() { - e.markUsed() - - return e.deepCopy(), true - } - - if !e.libRef[0].Matches(expectedRefPiece) { - return nil, false - } - e.markUsed() - childSchemaProcessing := e.deepCopy() - childSchemaProcessing.libRef = childSchemaProcessing.libRef[1:] - return childSchemaProcessing, !childSchemaProcessing.IntendedForAnotherLibrary() -} - -func (e *DocumentSchemaEnvelope) markUsed() { e.used = true } - -func (e *DocumentSchemaEnvelope) deepCopy() *DocumentSchemaEnvelope { - var copiedPieces []ref.LibraryRef - copiedPieces = append(copiedPieces, e.libRef...) - return &DocumentSchemaEnvelope{ - Doc: e.Doc.deepCopy(), - originalLibRef: e.originalLibRef, - libRef: copiedPieces, - } -} diff --git a/vendor/github.com/k14s/ytt/pkg/schema/type.go b/vendor/github.com/k14s/ytt/pkg/schema/type.go deleted file mode 100644 index 976f934b5..000000000 --- a/vendor/github.com/k14s/ytt/pkg/schema/type.go +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package schema - -import ( - "fmt" - - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -var _ yamlmeta.Type = (*DocumentType)(nil) -var _ yamlmeta.Type = (*MapType)(nil) -var _ yamlmeta.Type = (*MapItemType)(nil) -var _ yamlmeta.Type = (*ArrayType)(nil) -var _ yamlmeta.Type = (*ArrayItemType)(nil) -var _ yamlmeta.Type = (*AnyType)(nil) -var _ yamlmeta.Type = (*NullType)(nil) - -type DocumentType struct { - Source *yamlmeta.Document - ValueType yamlmeta.Type // typically one of: MapType, ArrayType, ScalarType - Position *filepos.Position - defaultValue interface{} -} -type MapType struct { - Items []*MapItemType - Position *filepos.Position -} -type MapItemType struct { - Key interface{} // usually a string - ValueType yamlmeta.Type - Position *filepos.Position - defaultValue interface{} -} -type ArrayType struct { - ItemsType yamlmeta.Type - Position *filepos.Position - defaultValue interface{} -} -type ArrayItemType struct { - ValueType yamlmeta.Type - Position *filepos.Position - defaultValue interface{} -} -type ScalarType struct { - ValueType interface{} - Position *filepos.Position - defaultValue interface{} -} -type AnyType struct { - ValueType yamlmeta.Type - Position *filepos.Position -} -type NullType struct { - ValueType yamlmeta.Type - Position *filepos.Position -} - -func (n NullType) GetDefaultValue() interface{} { - return nil -} - -func (a AnyType) GetDefaultValue() interface{} { - if a.ValueType == nil { - return nil - } - return a.ValueType.GetDefaultValue() // delegate GetDefaultValue() functions will make defensive copy 👍 -} - -func (m ScalarType) GetDefaultValue() interface{} { - return m.defaultValue // scalar values are copied (even through an interface{} reference) -} - -func (a ArrayItemType) GetDefaultValue() interface{} { - panic(fmt.Sprintf("Unexpected call to GetDefaultValue() on %+v", a)) -} - -func (a ArrayType) GetDefaultValue() interface{} { - defaultValues := &yamlmeta.Array{Position: a.Position} - return defaultValues -} - -func (t MapItemType) GetDefaultValue() interface{} { - return &yamlmeta.MapItem{Key: t.Key, Value: t.ValueType.GetDefaultValue(), Position: t.Position} -} - -func (m MapType) GetDefaultValue() interface{} { - defaultValues := &yamlmeta.Map{Position: m.Position} - for _, item := range m.Items { - newItem := item.GetDefaultValue() - defaultValues.Items = append(defaultValues.Items, newItem.(*yamlmeta.MapItem)) - } - return defaultValues -} - -func (t DocumentType) GetDefaultValue() interface{} { - return &yamlmeta.Document{Value: t.ValueType.GetDefaultValue(), Position: t.Position} -} - -func (n NullType) AssignTypeTo(typeable yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - childCheck := n.ValueType.AssignTypeTo(typeable) - chk.Violations = append(chk.Violations, childCheck.Violations...) - return -} - -func (n NullType) GetValueType() yamlmeta.Type { - return n.ValueType -} - -func (n NullType) CheckType(node yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - if len(node.GetValues()) == 1 && node.GetValues()[0] == nil { - return - } - - check := n.GetValueType().CheckType(node) - chk.Violations = check.Violations - - return -} - -func (n NullType) GetDefinitionPosition() *filepos.Position { - return n.Position -} - -func (n NullType) String() string { - return "null" -} - -func (t *DocumentType) GetValueType() yamlmeta.Type { - panic("Not implemented because it is unreachable") -} -func (m MapType) GetValueType() yamlmeta.Type { - panic("Not implemented because it is unreachable") -} -func (t MapItemType) GetValueType() yamlmeta.Type { - return t.ValueType -} -func (a ArrayType) GetValueType() yamlmeta.Type { - panic("Not implemented because it is unreachable") -} -func (a ArrayItemType) GetValueType() yamlmeta.Type { - return a.ValueType -} -func (m ScalarType) GetValueType() yamlmeta.Type { - panic("Not implemented because it is unreachable") -} -func (a AnyType) GetValueType() yamlmeta.Type { - return a -} - -func (t *DocumentType) GetDefinitionPosition() *filepos.Position { - return t.Position -} -func (m MapType) GetDefinitionPosition() *filepos.Position { - return m.Position -} -func (t MapItemType) GetDefinitionPosition() *filepos.Position { - return t.Position -} -func (a ArrayType) GetDefinitionPosition() *filepos.Position { - return a.Position -} -func (a ArrayItemType) GetDefinitionPosition() *filepos.Position { - return a.Position -} -func (m ScalarType) GetDefinitionPosition() *filepos.Position { - return m.Position -} -func (a AnyType) GetDefinitionPosition() *filepos.Position { - return a.Position -} - -func (t *DocumentType) String() string { - return "document" -} -func (m MapType) String() string { - return "map" -} -func (t MapItemType) String() string { - return fmt.Sprintf("%s: %s", t.Key, t.ValueType.String()) -} -func (a ArrayType) String() string { - return "array" -} -func (a ArrayItemType) String() string { - return fmt.Sprintf("- %s", a.ValueType.String()) -} -func (m ScalarType) String() string { - switch m.ValueType.(type) { - case float64: - return "float" - case int: - return "integer" - case bool: - return "boolean" - default: - return fmt.Sprintf("%T", m.ValueType) - } -} -func (a AnyType) String() string { - return "any" -} - -func (t *DocumentType) CheckType(_ yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - return -} - -func (m *MapType) CheckType(node yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - nodeMap, ok := node.(*yamlmeta.Map) - if !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, m)) - return - } - - for _, item := range nodeMap.Items { - if !m.AllowsKey(item.Key) { - chk.Violations = append(chk.Violations, - NewUnexpectedKeyAssertionError(item, m.Position)) - } - } - return -} - -func (t *MapItemType) CheckType(node yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - _, ok := node.(*yamlmeta.MapItem) - if !ok { - // A Map must've yielded a non-MapItem which is not valid YAML - panic(fmt.Sprintf("MapItem type check was called on a non-MapItem: %#v", node)) - } - - return -} - -func (a *ArrayType) CheckType(node yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - _, ok := node.(*yamlmeta.Array) - if !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, a)) - } - return -} - -func (a *ArrayItemType) CheckType(node yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - _, ok := node.(*yamlmeta.ArrayItem) - if !ok { - // An Array must've yielded a non-ArrayItem which is not valid YAML - panic(fmt.Sprintf("ArrayItem type check was called on a non-ArrayItem: %#v", node)) - } - return -} - -func (m *ScalarType) CheckType(node yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - value := node.GetValues()[0] - switch value.(type) { - case string: - if _, ok := m.ValueType.(string); !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, m)) - } - case float64: - if _, ok := m.ValueType.(float64); !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, m)) - } - case int, int64, uint64: - if _, ok := m.ValueType.(int); !ok { - if _, ok = m.ValueType.(float64); !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, m)) - } - } - case bool: - if _, ok := m.ValueType.(bool); !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, m)) - } - default: - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(node, m)) - } - return -} - -func (a AnyType) CheckType(_ yamlmeta.TypeWithValues) (chk yamlmeta.TypeCheck) { - return -} - -func (t *DocumentType) AssignTypeTo(typeable yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - doc, ok := typeable.(*yamlmeta.Document) - if !ok { - chk.Violations = append(chk.Violations, - NewMismatchedTypeAssertionError(typeable, t)) - return - } - doc.SetType(t) - typeableValue, isNode := doc.Value.(yamlmeta.Typeable) - if isNode { - childCheck := t.ValueType.AssignTypeTo(typeableValue) - chk.Violations = append(chk.Violations, childCheck.Violations...) - } // else, is a scalar - return chk -} - -func (m *MapType) AssignTypeTo(typeable yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - mapNode, ok := typeable.(*yamlmeta.Map) - if !ok { - chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(typeable, m)) - return - } - var foundKeys []interface{} - typeable.SetType(m) - for _, mapItem := range mapNode.Items { - for _, itemType := range m.Items { - if mapItem.Key == itemType.Key { - foundKeys = append(foundKeys, itemType.Key) - childCheck := itemType.AssignTypeTo(mapItem) - chk.Violations = append(chk.Violations, childCheck.Violations...) - break - } - } - } - - m.applySchemaDefaults(foundKeys, chk, mapNode) - return -} - -func (m *MapType) applySchemaDefaults(foundKeys []interface{}, chk yamlmeta.TypeCheck, mapNode *yamlmeta.Map) { - for _, item := range m.Items { - if contains(foundKeys, item.Key) { - continue - } - - val := item.GetDefaultValue() - childCheck := item.AssignTypeTo(val.(*yamlmeta.MapItem)) - chk.Violations = append(chk.Violations, childCheck.Violations...) - err := mapNode.AddValue(val) - if err != nil { - panic(fmt.Sprintf("Internal inconsistency: adding map item: %s", err)) - } - } -} - -func contains(haystack []interface{}, needle interface{}) bool { - for _, key := range haystack { - if key == needle { - return true - } - } - return false -} - -func (t *MapItemType) AssignTypeTo(typeable yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - mapItem, ok := typeable.(*yamlmeta.MapItem) - if !ok { - panic(fmt.Sprintf("Attempt to assign type to a non-map-item (children of Maps can only be MapItems). type=%#v; typeable=%#v", t, typeable)) - } - typeable.SetType(t) - typeableValue, isNode := mapItem.Value.(yamlmeta.Typeable) - if isNode { - childCheck := t.ValueType.AssignTypeTo(typeableValue) - chk.Violations = append(chk.Violations, childCheck.Violations...) - } // else, is scalar - return -} - -func (a *ArrayType) AssignTypeTo(typeable yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - arrayNode, ok := typeable.(*yamlmeta.Array) - if !ok { - chk.Violations = append(chk.Violations, NewMismatchedTypeAssertionError(typeable, a)) - return - } - typeable.SetType(a) - for _, arrayItem := range arrayNode.Items { - childCheck := a.ItemsType.AssignTypeTo(arrayItem) - chk.Violations = append(chk.Violations, childCheck.Violations...) - } - return -} - -func (a *ArrayItemType) AssignTypeTo(typeable yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - arrayItem, ok := typeable.(*yamlmeta.ArrayItem) - if !ok { - panic(fmt.Sprintf("Attempt to assign type to a non-array-item (children of Arrays can only be ArrayItems). type=%#v; typeable=%#v", a, typeable)) - } - typeable.SetType(a) - typeableValue, isNode := arrayItem.Value.(yamlmeta.Typeable) - if isNode { - childCheck := a.ValueType.AssignTypeTo(typeableValue) - chk.Violations = append(chk.Violations, childCheck.Violations...) - } // else, is scalar - return -} - -func (m *ScalarType) AssignTypeTo(typeable yamlmeta.Typeable) yamlmeta.TypeCheck { - return yamlmeta.TypeCheck{[]error{NewMismatchedTypeAssertionError(typeable, m)}} -} - -func (a AnyType) AssignTypeTo(yamlmeta.Typeable) (chk yamlmeta.TypeCheck) { - return -} - -func (m *MapType) AllowsKey(key interface{}) bool { - for _, item := range m.Items { - if item.Key == key { - return true - } - } - return false -} diff --git a/vendor/github.com/k14s/ytt/pkg/template/meta.go b/vendor/github.com/k14s/ytt/pkg/template/meta.go deleted file mode 100644 index 4459c02b0..000000000 --- a/vendor/github.com/k14s/ytt/pkg/template/meta.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package template - -import ( - "fmt" - "strings" -) - -type AnnotationName string -type AnnotationNs string - -const ( - AnnotationNameComment AnnotationName = "comment" -) - -type Meta struct { - Annotations []*Annotation -} - -type Annotation struct { - Name AnnotationName // eg template/code - Content string // eg if True: -} - -// Supported formats: -// "! comment" -// "@comment content" -// "@ if True:" -// "@template/code" -// "@template/code if True:" -// "@text/trim-left,text/trim-right,template/code if True:" - -type MetaOpts struct { - IgnoreUnknown bool -} - -func NewMetaFromString(data string, opts MetaOpts) (Meta, error) { - meta := Meta{} - - // TODO better error messages? - switch { - case len(data) > 0 && data[0] == '!': - meta.Annotations = []*Annotation{{ - Name: AnnotationNameComment, - Content: data[1:], - }} - - case len(data) > 0 && data[0] == '@': - pieces := strings.SplitN(data[1:], " ", 2) - for _, name := range strings.Split(pieces[0], ",") { - meta.Annotations = append(meta.Annotations, &Annotation{ - Name: AnnotationName(name), - }) - } - if len(pieces) == 2 { - meta.Annotations[len(meta.Annotations)-1].Content = pieces[1] - } - - default: - if opts.IgnoreUnknown { - meta.Annotations = []*Annotation{{ - Name: AnnotationNameComment, - Content: data, - }} - } else { - return Meta{}, fmt.Errorf("Unrecognized comment type (expected '#@' or '#!')") - } - } - - return meta, nil -} diff --git a/vendor/github.com/k14s/ytt/pkg/template/nodes.go b/vendor/github.com/k14s/ytt/pkg/template/nodes.go deleted file mode 100644 index 06e37094d..000000000 --- a/vendor/github.com/k14s/ytt/pkg/template/nodes.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package template - -import ( - "strconv" - - "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template/core" -) - -var ( - NodeTagRoot = NodeTag{-100} -) - -type Nodes struct { - id int - tagToNode map[NodeTag]EvaluationNode - childToParentTag map[NodeTag]NodeTag -} - -func NewNodes() *Nodes { - return &Nodes{ - tagToNode: map[NodeTag]EvaluationNode{}, - childToParentTag: map[NodeTag]NodeTag{}, - } -} - -func (n *Nodes) Ancestors() Ancestors { return NewAncestors(n.childToParentTag) } - -func (n *Nodes) AddRootNode(node EvaluationNode) NodeTag { - n.id++ - tag := NodeTag{n.id} - n.tagToNode[tag] = node - n.childToParentTag[tag] = NodeTagRoot - return tag -} - -func (n *Nodes) AddNode(node EvaluationNode, parentTag NodeTag) NodeTag { - n.id++ - tag := NodeTag{n.id} - n.tagToNode[tag] = node - n.childToParentTag[tag] = parentTag - return tag -} - -func (n *Nodes) FindNode(tag NodeTag) (EvaluationNode, bool) { - node, ok := n.tagToNode[tag] - return node, ok -} - -type NodeTag struct { - id int -} - -func NewNodeTag(id int) NodeTag { return NodeTag{id} } - -func NewNodeTagFromStarlarkValue(val starlark.Value) (NodeTag, error) { - id, err := core.NewStarlarkValue(val).AsInt64() - if err != nil { - return NodeTag{}, err - } - return NodeTag{int(id)}, nil -} - -func (t NodeTag) Equals(other NodeTag) bool { return t.id == other.id } -func (t NodeTag) String() string { return "node tag " + strconv.Itoa(t.id) } -func (t NodeTag) AsString() string { return strconv.Itoa(t.id) } diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/data_values.go b/vendor/github.com/k14s/ytt/pkg/workspace/data_values.go deleted file mode 100644 index 58c61813f..000000000 --- a/vendor/github.com/k14s/ytt/pkg/workspace/data_values.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package workspace - -import ( - "fmt" - "strings" - - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/workspace/ref" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -const ( - AnnotationLibraryRef = "library/ref" - - dvsLibrarySep = "@" -) - -type DataValues struct { - Doc *yamlmeta.Document - AfterLibMod bool - used bool - - originalLibRef []ref.LibraryRef - libRef []ref.LibraryRef -} - -func NewDataValues(doc *yamlmeta.Document) (*DataValues, error) { - libRef, afterLibMod, err := parseDVAnnotations(ref.LibraryRefExtractor{}, doc) - if err != nil { - return nil, err - } - - return &DataValues{Doc: doc, AfterLibMod: afterLibMod, libRef: libRef, originalLibRef: libRef}, nil -} - -func NewEmptyDataValues() *DataValues { - return &DataValues{Doc: newEmptyDataValuesDocument()} -} - -func newEmptyDataValuesDocument() *yamlmeta.Document { - return &yamlmeta.Document{ - Value: &yamlmeta.Map{}, - Position: filepos.NewUnknownPosition(), - } -} - -type ExtractLibRefs interface { - FromStr(string) ([]ref.LibraryRef, error) - FromAnnotation(template.NodeAnnotations) ([]ref.LibraryRef, error) -} - -func NewDataValuesWithLib(libRefs ExtractLibRefs, doc *yamlmeta.Document, libRefStr string) (*DataValues, error) { - libRefsFromStr, err := libRefs.FromStr(libRefStr) - if err != nil { - return nil, err - } - - libRefsFromAnnotation, afterLibMod, err := parseDVAnnotations(libRefs, doc) - if err != nil { - return nil, err - } else if len(libRefsFromAnnotation) > 0 { - panic(fmt.Sprintf("Library was provided as arg as well as with %s annotation", AnnotationLibraryRef)) - } - - return &DataValues{Doc: doc, AfterLibMod: afterLibMod, libRef: libRefsFromStr, originalLibRef: libRefsFromStr}, nil -} - -func NewDataValuesWithOptionalLib(doc *yamlmeta.Document, libRefStr string) (*DataValues, error) { - if len(libRefStr) > 0 { - return NewDataValuesWithLib(ref.LibraryRefExtractor{}, doc, libRefStr) - } - return NewDataValues(doc) -} - -func (dvd *DataValues) IsUsed() bool { return dvd.used } -func (dvd *DataValues) markUsed() { dvd.used = true } - -func (dvd *DataValues) Desc() string { - // TODO: Update to output file location of annotation. If no annotation use doc position although these will always be used - var desc []string - for _, refPiece := range dvd.originalLibRef { - desc = append(desc, refPiece.AsString()) - } - return fmt.Sprintf("Data Value belonging to library '%s%s' on %s", dvsLibrarySep, - strings.Join(desc, dvsLibrarySep), dvd.Doc.Position.AsString()) -} - -func (dvd *DataValues) IntendedForAnotherLibrary() bool { return len(dvd.libRef) > 0 } - -func (dvd *DataValues) UsedInLibrary(expectedRefPiece ref.LibraryRef) *DataValues { - if len(dvd.libRef) == 0 { - dvd.markUsed() - return dvd.deepCopy() - } - if !dvd.libRef[0].Matches(expectedRefPiece) { - return nil - } - dvd.markUsed() - childDV := dvd.deepCopy() - childDV.libRef = childDV.libRef[1:] - return childDV -} - -func (dvd *DataValues) deepCopy() *DataValues { - var copiedPieces []ref.LibraryRef - copiedPieces = append(copiedPieces, dvd.libRef...) - return &DataValues{Doc: dvd.Doc.DeepCopy(), AfterLibMod: dvd.AfterLibMod, - libRef: copiedPieces, originalLibRef: dvd.originalLibRef} -} - -func parseDVAnnotations(libRefs ExtractLibRefs, doc *yamlmeta.Document) ([]ref.LibraryRef, bool, error) { - var afterLibMod bool - anns := template.NewAnnotations(doc) - - libRef, err := libRefs.FromAnnotation(anns) - if err != nil { - return nil, false, err - } - - for _, kwarg := range anns.Kwargs(AnnotationDataValues) { - kwargName, err := core.NewStarlarkValue(kwarg[0]).AsString() - if err != nil { - return nil, false, err - } - - switch kwargName { - case "after_library_module": - afterLibMod, err = core.NewStarlarkValue(kwarg[1]).AsBool() - if err != nil { - return nil, false, err - } else if len(libRef) == 0 { - return nil, false, fmt.Errorf("Annotation %s: Expected kwarg 'after_library_module' to be used with %s annotation", - AnnotationDataValues, AnnotationLibraryRef) - } - default: - return nil, false, fmt.Errorf("Unknown kwarg %s for annotation %s", kwargName, AnnotationDataValues) - } - } - return libRef, afterLibMod, nil -} diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/data_values_pre_processing.go b/vendor/github.com/k14s/ytt/pkg/workspace/data_values_pre_processing.go deleted file mode 100644 index c984ff7ae..000000000 --- a/vendor/github.com/k14s/ytt/pkg/workspace/data_values_pre_processing.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package workspace - -import ( - "fmt" - "strings" - - "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/schema" - "github.com/k14s/ytt/pkg/yamlmeta" - yttoverlay "github.com/k14s/ytt/pkg/yttlibrary/overlay" -) - -type DataValuesPreProcessing struct { - valuesFiles []*FileInLibrary - valuesOverlays []*DataValues - schema Schema - loader *TemplateLoader - IgnoreUnknownComments bool // TODO remove? -} - -func (o DataValuesPreProcessing) Apply() (*DataValues, []*DataValues, error) { - files := append([]*FileInLibrary{}, o.valuesFiles...) - - // Respect assigned file order for data values overlaying to succeed - SortFilesInLibrary(files) - - dataValues, libraryDataValues, err := o.apply(files) - if err != nil { - errMsg := "Overlaying data values (in following order: %s): %s" - return nil, nil, fmt.Errorf(errMsg, o.allFileDescs(files), err) - } - - return dataValues, libraryDataValues, nil -} - -func (o DataValuesPreProcessing) apply(files []*FileInLibrary) (*DataValues, []*DataValues, error) { - allDvs, err := o.collectDataValuesDocs(files) - if err != nil { - return nil, nil, err - } - - // merge all Data Values YAML documents into one - var otherLibraryDVs []*DataValues - var resultDVsDoc *yamlmeta.Document - for _, dv := range allDvs { - if dv.IntendedForAnotherLibrary() { - otherLibraryDVs = append(otherLibraryDVs, dv) - continue - } - - if resultDVsDoc == nil { - resultDVsDoc = dv.Doc - } else { - resultDVsDoc, err = o.overlay(resultDVsDoc, dv.Doc) - if err != nil { - return nil, nil, err - } - } - typeCheck := o.typeAndCheck(resultDVsDoc) - if len(typeCheck.Violations) > 0 { - return nil, nil, schema.NewSchemaError("One or more data values were invalid", typeCheck.Violations...) - } - } - - if resultDVsDoc == nil { - resultDVsDoc = newEmptyDataValuesDocument() - } - dataValues, err := NewDataValues(resultDVsDoc) - if err != nil { - return nil, nil, err - } - return dataValues, otherLibraryDVs, nil -} - -func (o DataValuesPreProcessing) collectDataValuesDocs(files []*FileInLibrary) ([]*DataValues, error) { - var allDvs []*DataValues - if defaults := o.schema.DefaultDataValues(); defaults != nil { - dv, err := NewDataValues(defaults) - if err != nil { - return nil, err - } - // o.schema has already been determined to be the schema for the current library. - // set the default data value libref to nil, signaling that it is for the current library. - dv.libRef = nil - allDvs = append(allDvs, dv) - } - for _, fileInLib := range files { - docs, err := o.extractDataValueDocs(fileInLib) - if err != nil { - return nil, fmt.Errorf("Templating file '%s': %s", fileInLib.File.RelativePath(), err) - } - for _, doc := range docs { - dv, err := NewDataValues(doc) - if err != nil { - return nil, err - } - allDvs = append(allDvs, dv) - } - } - allDvs = append(allDvs, o.valuesOverlays...) - return allDvs, nil -} - -func (o DataValuesPreProcessing) typeAndCheck(dataValuesDoc *yamlmeta.Document) yamlmeta.TypeCheck { - chk := o.schema.AssignType(dataValuesDoc) - if _, checkable := o.schema.(*schema.DocumentSchema); checkable { - if len(chk.Violations) > 0 { - return chk - } - chk = dataValuesDoc.Check() - } - return chk -} - -func (o DataValuesPreProcessing) allFileDescs(files []*FileInLibrary) string { - var result []string - for _, fileInLib := range files { - result = append(result, fileInLib.File.RelativePath()) - } - if len(o.valuesOverlays) > 0 { - result = append(result, "additional data values") - } - return strings.Join(result, ", ") -} - -func (o DataValuesPreProcessing) extractDataValueDocs(fileInLib *FileInLibrary) ([]*yamlmeta.Document, error) { - libraryCtx := LibraryExecutionContext{Current: fileInLib.Library, Root: NewRootLibrary(nil)} - - _, resultDocSet, err := o.loader.EvalYAML(libraryCtx, fileInLib.File) - if err != nil { - return nil, err - } - - // Extract _all_ data values docs from the templated result - valuesDocs, nonValuesDocs, err := DocExtractor{resultDocSet}.Extract(AnnotationDataValues) - if err != nil { - return nil, err - } - - // Fail if there any non-empty docs that are not data values - if len(nonValuesDocs) > 0 { - for _, doc := range nonValuesDocs { - if !doc.IsEmpty() { - errStr := "Expected data values file '%s' to only have data values documents" - return nil, fmt.Errorf(errStr, fileInLib.File.RelativePath()) - } - } - } - - return valuesDocs, nil -} - -func (o DataValuesPreProcessing) overlay(dataValues, overlay *yamlmeta.Document) (*yamlmeta.Document, error) { - op := yttoverlay.Op{ - Left: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{dataValues}}, - Right: &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{overlay}}, - Thread: &starlark.Thread{Name: "data-values-pre-processing"}, - - ExactMatch: true, - } - - newLeft, err := op.Apply() - if err != nil { - return nil, err - } - - return newLeft.(*yamlmeta.DocumentSet).Items[0], nil -} diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/library_execution_factory.go b/vendor/github.com/k14s/ytt/pkg/workspace/library_execution_factory.go deleted file mode 100644 index b83154cca..000000000 --- a/vendor/github.com/k14s/ytt/pkg/workspace/library_execution_factory.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package workspace - -import ( - "github.com/k14s/ytt/pkg/cmd/ui" -) - -type LibraryExecutionContext struct { - Current *Library - Root *Library -} - -type LibraryExecutionFactory struct { - ui ui.UI - templateLoaderOpts TemplateLoaderOpts -} - -func NewLibraryExecutionFactory(ui ui.UI, templateLoaderOpts TemplateLoaderOpts) *LibraryExecutionFactory { - return &LibraryExecutionFactory{ui, templateLoaderOpts} -} - -func (f *LibraryExecutionFactory) WithTemplateLoaderOptsOverrides(overrides TemplateLoaderOptsOverrides) *LibraryExecutionFactory { - return NewLibraryExecutionFactory(f.ui, f.templateLoaderOpts.Merge(overrides)) -} - -func (f *LibraryExecutionFactory) New(ctx LibraryExecutionContext) *LibraryExecution { - return NewLibraryExecution(ctx, f.ui, f.templateLoaderOpts, f) -} diff --git a/vendor/github.com/k14s/ytt/pkg/workspace/schema.go b/vendor/github.com/k14s/ytt/pkg/workspace/schema.go deleted file mode 100644 index db62defbb..000000000 --- a/vendor/github.com/k14s/ytt/pkg/workspace/schema.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 -package workspace - -import ( - "github.com/k14s/ytt/pkg/schema" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -type Schema interface { - AssignType(typeable yamlmeta.Typeable) yamlmeta.TypeCheck - // DefaultDataValues yields default values for Data Values... - // if schema was built by schema.NewNullSchema (i.e. no schema was provided), returns nil - DefaultDataValues() *yamlmeta.Document -} - -var _ Schema = &schema.DocumentSchema{} diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/node.go b/vendor/github.com/k14s/ytt/pkg/yamlmeta/node.go deleted file mode 100644 index 2c8a3cbc9..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/node.go +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yamlmeta - -import ( - "encoding/json" - "fmt" - - "github.com/k14s/ytt/pkg/filepos" - "github.com/k14s/ytt/pkg/orderedmap" - "github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2" -) - -func (ds *DocumentSet) GetPosition() *filepos.Position { return ds.Position } -func (d *Document) GetPosition() *filepos.Position { return d.Position } -func (m *Map) GetPosition() *filepos.Position { return m.Position } -func (mi *MapItem) GetPosition() *filepos.Position { return mi.Position } -func (a *Array) GetPosition() *filepos.Position { return a.Position } -func (ai *ArrayItem) GetPosition() *filepos.Position { return ai.Position } -func (s *Scalar) GetPosition() *filepos.Position { return s.Position } - -func (ds *DocumentSet) SetPosition(position *filepos.Position) { ds.Position = position } -func (d *Document) SetPosition(position *filepos.Position) { d.Position = position } -func (m *Map) SetPosition(position *filepos.Position) { m.Position = position } -func (mi *MapItem) SetPosition(position *filepos.Position) { mi.Position = position } -func (a *Array) SetPosition(position *filepos.Position) { a.Position = position } -func (ai *ArrayItem) SetPosition(position *filepos.Position) { ai.Position = position } - -func (ds *DocumentSet) ValueTypeAsString() string { return "documentSet" } -func (d *Document) ValueTypeAsString() string { return typeToString(d.Value) } -func (m *Map) ValueTypeAsString() string { return "map" } -func (mi *MapItem) ValueTypeAsString() string { return typeToString(mi.Value) } -func (a *Array) ValueTypeAsString() string { return "array" } -func (ai *ArrayItem) ValueTypeAsString() string { return typeToString(ai.Value) } -func (s *Scalar) ValueTypeAsString() string { return typeToString(s.Value) } - -func typeToString(value interface{}) string { - switch value.(type) { - case float64: - return "float" - case int, int64, uint64: - return "integer" - case bool: - return "boolean" - case nil: - return "null" - default: - if t, ok := value.(TypeWithValues); ok { - return t.ValueTypeAsString() - } - return fmt.Sprintf("%T", value) - } -} - -func (ds *DocumentSet) SetValue(val interface{}) error { - return fmt.Errorf("cannot set value on a documentset") -} - -func (d *Document) SetValue(val interface{}) error { - d.ResetValue() - return d.AddValue(val) -} - -func (m *Map) SetValue(val interface{}) error { - return fmt.Errorf("cannot set value on a map") -} - -func (mi *MapItem) SetValue(val interface{}) error { - mi.ResetValue() - return mi.AddValue(val) -} - -func (a *Array) SetValue(val interface{}) error { - return fmt.Errorf("cannot set value on an array") -} - -func (ai *ArrayItem) SetValue(val interface{}) error { - ai.ResetValue() - return ai.AddValue(val) -} - -func isValidValue(val interface{}) bool { - switch val.(type) { - case *Map, *orderedmap.Map, - *Array, []interface{}, - int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, - float32, float64, - bool, - string, - nil: - return true - default: - return false - } -} - -func (ds *DocumentSet) ResetValue() { ds.Items = nil } -func (d *Document) ResetValue() { d.Value = nil } -func (m *Map) ResetValue() { m.Items = nil } -func (mi *MapItem) ResetValue() { mi.Value = nil } -func (a *Array) ResetValue() { a.Items = nil } -func (ai *ArrayItem) ResetValue() { ai.Value = nil } - -func (ds *DocumentSet) AddValue(val interface{}) error { - if item, ok := val.(*Document); ok { - ds.Items = append(ds.Items, item) - return nil - } - return fmt.Errorf("cannot add non-document value (%T) into documentset", val) -} - -func (d *Document) AddValue(val interface{}) error { - if !isValidValue(val) { - return fmt.Errorf("documents can only contain arrays, maps, or scalars; this is a %T", val) - } - d.Value = val - return nil -} - -func (m *Map) AddValue(val interface{}) error { - if item, ok := val.(*MapItem); ok { - m.Items = append(m.Items, item) - return nil - } - return fmt.Errorf("cannot add non-map-item value (%T) into map", val) -} - -func (mi *MapItem) AddValue(val interface{}) error { - if !isValidValue(val) { - return fmt.Errorf("mapitems can only contain arrays, maps, or scalars; this is a %T", val) - } - mi.Value = val - return nil -} - -func (a *Array) AddValue(val interface{}) error { - if item, ok := val.(*ArrayItem); ok { - a.Items = append(a.Items, item) - return nil - } - return fmt.Errorf("cannot add non-array-item value (%T) into array", val) -} - -func (ai *ArrayItem) AddValue(val interface{}) error { - if !isValidValue(val) { - return fmt.Errorf("arrayitems can only contain maps, arrays, or scalars; this is a %T", val) - } - ai.Value = val - return nil -} - -func (ds *DocumentSet) GetValues() []interface{} { - var result []interface{} - for _, item := range ds.Items { - result = append(result, item) - } - return result -} - -func (d *Document) GetValues() []interface{} { return []interface{}{d.Value} } - -func (m *Map) GetValues() []interface{} { - var result []interface{} - for _, item := range m.Items { - result = append(result, item) - } - return result -} - -func (mi *MapItem) GetValues() []interface{} { return []interface{}{mi.Value} } - -func (a *Array) GetValues() []interface{} { - var result []interface{} - for _, item := range a.Items { - result = append(result, item) - } - return result -} - -func (ai *ArrayItem) GetValues() []interface{} { return []interface{}{ai.Value} } -func (s *Scalar) GetValues() []interface{} { return []interface{}{s.Value} } - -func (ds *DocumentSet) GetComments() []*Comment { return ds.Comments } -func (d *Document) GetComments() []*Comment { return d.Comments } -func (m *Map) GetComments() []*Comment { return m.Comments } -func (mi *MapItem) GetComments() []*Comment { return mi.Comments } -func (a *Array) GetComments() []*Comment { return a.Comments } -func (ai *ArrayItem) GetComments() []*Comment { return ai.Comments } - -func (ds *DocumentSet) addComments(comment *Comment) { ds.Comments = append(ds.Comments, comment) } -func (d *Document) addComments(comment *Comment) { d.Comments = append(d.Comments, comment) } -func (m *Map) addComments(comment *Comment) { - panic(fmt.Sprintf("Attempted to attach comment (%s) to Map (%v); maps cannot carry comments", comment.Data, m)) -} -func (mi *MapItem) addComments(comment *Comment) { mi.Comments = append(mi.Comments, comment) } -func (a *Array) addComments(comment *Comment) { - panic(fmt.Sprintf("Attempted to attach comment (%s) to Array (%v); arrays cannot carry comments", comment.Data, a)) -} -func (ai *ArrayItem) addComments(comment *Comment) { ai.Comments = append(ai.Comments, comment) } - -func (ds *DocumentSet) GetAnnotations() interface{} { return ds.annotations } -func (d *Document) GetAnnotations() interface{} { return d.annotations } -func (m *Map) GetAnnotations() interface{} { return m.annotations } -func (mi *MapItem) GetAnnotations() interface{} { return mi.annotations } -func (a *Array) GetAnnotations() interface{} { return a.annotations } -func (ai *ArrayItem) GetAnnotations() interface{} { return ai.annotations } - -func (ds *DocumentSet) SetAnnotations(anns interface{}) { ds.annotations = anns } -func (d *Document) SetAnnotations(anns interface{}) { d.annotations = anns } -func (m *Map) SetAnnotations(anns interface{}) { m.annotations = anns } -func (mi *MapItem) SetAnnotations(anns interface{}) { mi.annotations = anns } -func (a *Array) SetAnnotations(anns interface{}) { a.annotations = anns } -func (ai *ArrayItem) SetAnnotations(anns interface{}) { ai.annotations = anns } - -type TypeCheck struct { - Violations []error -} - -func (tc TypeCheck) Error() string { - if !tc.HasViolations() { - return "" - } - - msg := "" - for _, err := range tc.Violations { - msg += err.Error() + "\n" - } - return msg -} - -func (tc *TypeCheck) HasViolations() bool { - return len(tc.Violations) > 0 -} - -func (ds *DocumentSet) Check() TypeCheck { return TypeCheck{} } -func (d *Document) Check() (chk TypeCheck) { - switch typedContents := d.Value.(type) { - case Node: - chk = typedContents.Check() - } - - return chk -} -func (m *Map) Check() (chk TypeCheck) { - if m.Type == nil { - return - } - check := m.Type.CheckType(m) - if check.HasViolations() { - chk.Violations = append(chk.Violations, check.Violations...) - return - } - - for _, item := range m.Items { - check = item.Check() - if check.HasViolations() { - chk.Violations = append(chk.Violations, check.Violations...) - } - } - return -} -func (mi *MapItem) Check() (chk TypeCheck) { - check := mi.Type.CheckType(mi) - if check.HasViolations() { - chk.Violations = check.Violations - return - } - - check = checkCollectionItem(mi.Value, mi.Type.GetValueType(), mi.Position) - if check.HasViolations() { - chk.Violations = append(chk.Violations, check.Violations...) - } - return -} -func (a *Array) Check() (chk TypeCheck) { - for _, item := range a.Items { - check := item.Check() - if check.HasViolations() { - chk.Violations = append(chk.Violations, check.Violations...) - } - } - return -} -func (ai *ArrayItem) Check() (chk TypeCheck) { - if ai.Type == nil { - return - } - // TODO: This check only ensures that the ai is of ArrayItem type - // which we know because if it was not we would not assign - // the type to it. - // Given this maybe we can completely remove this check - // Lets not forget that the check of the type of the item - // is done by checkCollectionItem - chk = ai.Type.CheckType(ai) - if chk.HasViolations() { - return - } - - check := checkCollectionItem(ai.Value, ai.Type.GetValueType(), ai.Position) - if check.HasViolations() { - chk.Violations = append(chk.Violations, check.Violations...) - } - return chk -} - -// is it possible to enter this function with valueType=NullType or AnyType? -func checkCollectionItem(value interface{}, valueType Type, position *filepos.Position) (chk TypeCheck) { - switch typedValue := value.(type) { - case *Map: - check := typedValue.Check() - chk.Violations = append(chk.Violations, check.Violations...) - case *Array: - check := typedValue.Check() - chk.Violations = append(chk.Violations, check.Violations...) - default: - chk = valueType.CheckType(&Scalar{Value: value, Position: position}) - } - return chk -} - -// Below methods disallow marshaling of nodes directly -var _ []yaml.Marshaler = []yaml.Marshaler{&DocumentSet{}, &Document{}, &Map{}, &MapItem{}, &Array{}, &ArrayItem{}} - -func (ds *DocumentSet) MarshalYAML() (interface{}, error) { panic("Unexpected marshaling of docset") } -func (d *Document) MarshalYAML() (interface{}, error) { panic("Unexpected marshaling of doc") } -func (m *Map) MarshalYAML() (interface{}, error) { panic("Unexpected marshaling of map") } -func (mi *MapItem) MarshalYAML() (interface{}, error) { panic("Unexpected marshaling of mapitem") } -func (a *Array) MarshalYAML() (interface{}, error) { panic("Unexpected marshaling of array") } -func (ai *ArrayItem) MarshalYAML() (interface{}, error) { panic("Unexpected marshaling of arrayitem") } - -// Below methods disallow marshaling of nodes directly -var _ []json.Marshaler = []json.Marshaler{&DocumentSet{}, &Document{}, &Map{}, &MapItem{}, &Array{}, &ArrayItem{}} - -func (ds *DocumentSet) MarshalJSON() ([]byte, error) { panic("Unexpected marshaling of docset") } -func (d *Document) MarshalJSON() ([]byte, error) { panic("Unexpected marshaling of doc") } -func (m *Map) MarshalJSON() ([]byte, error) { panic("Unexpected marshaling of map") } -func (mi *MapItem) MarshalJSON() ([]byte, error) { panic("Unexpected marshaling of mapitem") } -func (a *Array) MarshalJSON() ([]byte, error) { panic("Unexpected marshaling of array") } -func (ai *ArrayItem) MarshalJSON() ([]byte, error) { panic("Unexpected marshaling of arrayitem") } - -func (ds *DocumentSet) sealed() {} -func (d *Document) sealed() {} -func (m *Map) sealed() {} -func (mi *MapItem) sealed() {} -func (a *Array) sealed() {} -func (ai *ArrayItem) sealed() {} diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/type.go b/vendor/github.com/k14s/ytt/pkg/yamlmeta/type.go deleted file mode 100644 index 163e39a5f..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/type.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yamlmeta - -import ( - "github.com/k14s/ytt/pkg/filepos" -) - -type Type interface { - AssignTypeTo(typeable Typeable) TypeCheck - GetValueType() Type - GetDefaultValue() interface{} - CheckType(node TypeWithValues) TypeCheck - GetDefinitionPosition() *filepos.Position - String() string -} - -type TypeWithValues interface { - GetValues() []interface{} - GetPosition() *filepos.Position - ValueTypeAsString() string -} - -type Typeable interface { - TypeWithValues - - SetType(Type) -} - -var _ Typeable = (*Document)(nil) -var _ Typeable = (*Map)(nil) -var _ Typeable = (*MapItem)(nil) -var _ Typeable = (*Array)(nil) -var _ Typeable = (*ArrayItem)(nil) - -func (d *Document) SetType(t Type) { d.Type = t } -func (m *Map) SetType(t Type) { m.Type = t } -func (mi *MapItem) SetType(t Type) { mi.Type = t } -func (a *Array) SetType(t Type) { a.Type = t } -func (ai *ArrayItem) SetType(t Type) { ai.Type = t } diff --git a/vendor/github.com/k14s/ytt/pkg/yamlmeta/value_holding_node.go b/vendor/github.com/k14s/ytt/pkg/yamlmeta/value_holding_node.go deleted file mode 100644 index 760fb2c2f..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yamlmeta/value_holding_node.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yamlmeta - -func (d *Document) Val() interface{} { - return d.Value -} -func (mi *MapItem) Val() interface{} { - return mi.Value -} -func (ai *ArrayItem) Val() interface{} { - return ai.Value -} diff --git a/vendor/github.com/k14s/ytt/pkg/yamltemplate/metas.go b/vendor/github.com/k14s/ytt/pkg/yamltemplate/metas.go deleted file mode 100644 index 5b103385f..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yamltemplate/metas.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yamltemplate - -import ( - "fmt" - "strings" - "unicode" - - "github.com/k14s/ytt/pkg/template" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -var ( - nodeSpecificKeywords = map[string]string{ - "if/end": "if", - "else/end": "else", - "elif/end": "elif", - "for/end": "for", - "def/end": "def", - } -) - -type Metas struct { - Block []*yamlmeta.Comment // meant to execute some code - Values []*yamlmeta.Comment // meant to return interpolated value - Annotations []CommentAndAnnotation - needsEnds int -} - -type CommentAndAnnotation struct { - Comment *yamlmeta.Comment - Annotation *template.Annotation -} - -type MetasOpts struct { - IgnoreUnknown bool -} - -func NewTemplateMetaFromYAMLComment(comment *yamlmeta.Comment, opts MetasOpts) (template.Meta, error) { - meta, err := template.NewMetaFromString(comment.Data, template.MetaOpts{IgnoreUnknown: opts.IgnoreUnknown}) - if err != nil { - return template.Meta{}, fmt.Errorf( - "Non-ytt comment at %s: '#%s': %s. (hint: if this is plain YAML — not a template — consider `--file-mark ':type=yaml-plain'`)", - comment.Position.AsString(), comment.Data, err) - } - return meta, nil -} - -func NewMetas(node yamlmeta.Node, opts MetasOpts) (Metas, error) { - metas := Metas{} - - for _, comment := range node.GetComments() { - meta, err := NewTemplateMetaFromYAMLComment(comment, opts) - if err != nil { - return metas, err - } - - for _, ann := range meta.Annotations { - if len(ann.Name) == 0 { - // Default code and value annotations to make templates less verbose - ann.Name = template.AnnotationCode - - if node.GetPosition().IsKnown() { - if comment.Position.LineNum() == node.GetPosition().LineNum() { - if len(node.GetValues()) > 0 && node.GetValues()[0] != nil { - return metas, fmt.Errorf( - "Expected YAML node at %s to have either computed or YAML value, but found both", - comment.Position.AsString()) - } - - ann.Name = template.AnnotationValue - } - } - } - - switch ann.Name { - case template.AnnotationValue: - metas.Values = append(metas.Values, &yamlmeta.Comment{ - Position: comment.Position, - Data: ann.Content, - }) - - case template.AnnotationCode: - if metas.needsEnds > 0 { - return metas, fmt.Errorf( - "Unexpected code at %s after use of '*/end', expected YAML node", - comment.Position.AsString()) - } - - code := ann.Content - spacePrefix := metas.spacePrefix(code) - - for keyword, replacementKeyword := range nodeSpecificKeywords { - if strings.HasPrefix(code, spacePrefix+keyword) { - metas.needsEnds++ - code = strings.Replace(code, spacePrefix+keyword, spacePrefix+replacementKeyword, 1) - } - } - - metas.Block = append(metas.Block, &yamlmeta.Comment{ - Position: comment.Position, - Data: code, - }) - - case template.AnnotationComment: - // ignore - - default: - metas.Annotations = append(metas.Annotations, CommentAndAnnotation{comment, ann}) - } - } - } - - return metas, nil -} - -func (m Metas) NeedsEnd() bool { return m.needsEnds != 0 } - -func (m Metas) spacePrefix(str string) string { - for i, r := range str { - if !unicode.IsSpace(r) { - return str[:i] - } - } - return "" -} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/all.go b/vendor/github.com/k14s/ytt/pkg/yttlibrary/all.go deleted file mode 100644 index 95868e53a..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/all.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yttlibrary - -import ( - "fmt" - - "github.com/k14s/starlark-go/starlark" - tplcore "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yttlibrary/overlay" -) - -type API struct { - modules map[string]starlark.StringDict -} - -func NewAPI(replaceNodeFunc tplcore.StarlarkFunc, dataMod DataModule, - libraryMod starlark.StringDict) API { - - return API{map[string]starlark.StringDict{ - "assert": AssertAPI, - "regexp": RegexpAPI, - - // Hashes - "md5": MD5API, - "sha256": SHA256API, - - // Serializations - "base64": Base64API, - "json": JSONAPI, - "yaml": YAMLAPI, - "url": URLAPI, - - // Templating - "template": NewTemplateModule(replaceNodeFunc).AsModule(), - "data": dataMod.AsModule(), - - // Object building - "struct": StructAPI, - "module": ModuleAPI, - "overlay": overlay.API, - - // Versioning - "version": VersionAPI, - - "library": libraryMod, - }} -} - -func (a API) FindModule(module string) (starlark.StringDict, error) { - if module, found := a.modules[module]; found { - return module, nil - } - return nil, fmt.Errorf("builtin ytt library does not have module '%s' "+ - "(hint: is it available in newer version of ytt?)", module) -} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/assert.go b/vendor/github.com/k14s/ytt/pkg/yttlibrary/assert.go deleted file mode 100644 index 103d10611..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/assert.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yttlibrary - -import ( - "fmt" - - "github.com/k14s/starlark-go/starlark" - "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" -) - -var ( - AssertAPI = starlark.StringDict{ - "assert": &starlarkstruct.Module{ - Name: "assert", - Members: starlark.StringDict{ - "fail": starlark.NewBuiltin("assert.fail", core.ErrWrapper(assertModule{}.Fail)), - }, - }, - } -) - -type assertModule struct{} - -func (b assertModule) Fail(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { - if args.Len() != 1 { - return starlark.None, fmt.Errorf("expected exactly one argument") - } - - val, err := core.NewStarlarkValue(args.Index(0)).AsString() - if err != nil { - return starlark.None, err - } - - return starlark.None, fmt.Errorf("fail: %s", val) -} diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/insert_annotation.go b/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/insert_annotation.go deleted file mode 100644 index 1c3aa1313..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/overlay/insert_annotation.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package overlay - -import ( - "fmt" - - "github.com/k14s/starlark-go/starlark" - "github.com/k14s/ytt/pkg/template" - tplcore "github.com/k14s/ytt/pkg/template/core" -) - -type InsertAnnotation struct { - newItem template.EvaluationNode - before bool - after bool -} - -func NewInsertAnnotation(newItem template.EvaluationNode) (InsertAnnotation, error) { - annotation := InsertAnnotation{newItem: newItem} - anns := template.NewAnnotations(newItem) - - if !anns.Has(AnnotationInsert) { - return annotation, fmt.Errorf( - "Expected item to have '%s' annotation", AnnotationInsert) - } - - kwargs := anns.Kwargs(AnnotationInsert) - if len(kwargs) == 0 { - return annotation, fmt.Errorf("Expected '%s' annotation to have "+ - "at least one keyword argument (before=..., after=...)", AnnotationInsert) - } - - for _, kwarg := range kwargs { - kwargName := string(kwarg[0].(starlark.String)) - - switch kwargName { - case "before": - resultBool, err := tplcore.NewStarlarkValue(kwarg[1]).AsBool() - if err != nil { - return InsertAnnotation{}, err - } - annotation.before = resultBool - - case "after": - resultBool, err := tplcore.NewStarlarkValue(kwarg[1]).AsBool() - if err != nil { - return InsertAnnotation{}, err - } - annotation.after = resultBool - - default: - return annotation, fmt.Errorf( - "Unknown '%s' annotation keyword argument '%s'", AnnotationInsert, kwargName) - } - } - - return annotation, nil -} - -func (a InsertAnnotation) IsBefore() bool { return a.before } -func (a InsertAnnotation) IsAfter() bool { return a.after } diff --git a/vendor/github.com/k14s/ytt/pkg/yttlibrary/yaml.go b/vendor/github.com/k14s/ytt/pkg/yttlibrary/yaml.go deleted file mode 100644 index 222a9c373..000000000 --- a/vendor/github.com/k14s/ytt/pkg/yttlibrary/yaml.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2020 VMware, Inc. -// SPDX-License-Identifier: Apache-2.0 - -package yttlibrary - -import ( - "fmt" - - "github.com/k14s/starlark-go/starlark" - "github.com/k14s/starlark-go/starlarkstruct" - "github.com/k14s/ytt/pkg/template/core" - "github.com/k14s/ytt/pkg/yamlmeta" -) - -var ( - YAMLAPI = starlark.StringDict{ - "yaml": &starlarkstruct.Module{ - Name: "yaml", - Members: starlark.StringDict{ - "encode": starlark.NewBuiltin("yaml.encode", core.ErrWrapper(yamlModule{}.Encode)), - "decode": starlark.NewBuiltin("yaml.decode", core.ErrWrapper(yamlModule{}.Decode)), - }, - }, - } -) - -type yamlModule struct{} - -func (b yamlModule) Encode(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { - if args.Len() != 1 { - return starlark.None, fmt.Errorf("expected exactly one argument") - } - - val, err := core.NewStarlarkValue(args.Index(0)).AsGoValue() - if err != nil { - return starlark.None, err - } - - var docSet *yamlmeta.DocumentSet - - switch typedVal := val.(type) { - case *yamlmeta.DocumentSet: - docSet = typedVal - case *yamlmeta.Document: - // Documents should be part of DocumentSet by the time it makes it here - panic("Unexpected document") - default: - docSet = &yamlmeta.DocumentSet{Items: []*yamlmeta.Document{{Value: typedVal}}} - } - - valBs, err := docSet.AsBytes() - if err != nil { - return starlark.None, err - } - - return starlark.String(string(valBs)), nil -} - -func (b yamlModule) Decode(thread *starlark.Thread, f *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { - if args.Len() != 1 { - return starlark.None, fmt.Errorf("expected exactly one argument") - } - - valEncoded, err := core.NewStarlarkValue(args.Index(0)).AsString() - if err != nil { - return starlark.None, err - } - - var valDecoded interface{} - - err = yamlmeta.PlainUnmarshal([]byte(valEncoded), &valDecoded) - if err != nil { - return starlark.None, err - } - - return core.NewGoValue(valDecoded).AsStarlarkValue(), nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9ce839e1e..821868946 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,6 +1,28 @@ # carvel.dev/vendir v0.40.0 ## explicit; go 1.21 carvel.dev/vendir/pkg/vendir/versions/v1alpha1 +# carvel.dev/ytt v0.51.0 +## explicit; go 1.23.2 +carvel.dev/ytt/pkg/cmd/template +carvel.dev/ytt/pkg/cmd/ui +carvel.dev/ytt/pkg/filepos +carvel.dev/ytt/pkg/files +carvel.dev/ytt/pkg/orderedmap +carvel.dev/ytt/pkg/schema +carvel.dev/ytt/pkg/spell +carvel.dev/ytt/pkg/template +carvel.dev/ytt/pkg/template/core +carvel.dev/ytt/pkg/texttemplate +carvel.dev/ytt/pkg/validations +carvel.dev/ytt/pkg/version +carvel.dev/ytt/pkg/workspace +carvel.dev/ytt/pkg/workspace/datavalues +carvel.dev/ytt/pkg/workspace/ref +carvel.dev/ytt/pkg/yamlmeta +carvel.dev/ytt/pkg/yamlmeta/internal/yaml.v2 +carvel.dev/ytt/pkg/yamltemplate +carvel.dev/ytt/pkg/yttlibrary +carvel.dev/ytt/pkg/yttlibrary/overlay # github.com/beorn7/perks v1.0.1 ## explicit; go 1.11 github.com/beorn7/perks/quantile @@ -106,25 +128,6 @@ github.com/k14s/starlark-go/resolve github.com/k14s/starlark-go/starlark github.com/k14s/starlark-go/starlarkstruct github.com/k14s/starlark-go/syntax -# github.com/k14s/ytt v0.36.0 -## explicit; go 1.16 -github.com/k14s/ytt/pkg/cmd/template -github.com/k14s/ytt/pkg/cmd/ui -github.com/k14s/ytt/pkg/filepos -github.com/k14s/ytt/pkg/files -github.com/k14s/ytt/pkg/orderedmap -github.com/k14s/ytt/pkg/schema -github.com/k14s/ytt/pkg/template -github.com/k14s/ytt/pkg/template/core -github.com/k14s/ytt/pkg/texttemplate -github.com/k14s/ytt/pkg/version -github.com/k14s/ytt/pkg/workspace -github.com/k14s/ytt/pkg/workspace/ref -github.com/k14s/ytt/pkg/yamlmeta -github.com/k14s/ytt/pkg/yamlmeta/internal/yaml.v2 -github.com/k14s/ytt/pkg/yamltemplate -github.com/k14s/ytt/pkg/yttlibrary -github.com/k14s/ytt/pkg/yttlibrary/overlay # github.com/mailru/easyjson v0.7.7 ## explicit; go 1.12 github.com/mailru/easyjson/buffer